2012-04-01 5 views
0

Я переношу онлайн-игру из Linux в Windows. В Linux все работает отлично, но на окнах у меня странное поведение. Клиент и сервер взаимодействуют через постоянное TCP-соединение. Сервер отправляет пакет каждые 0,5 секунды. И в Linux я получаю пакет каждые 0,5 секунды, но в окнах у меня есть что-то вроде этого: 0.9.0.3,0.3,0.3,0.9 и т. Д. (Интервал, фактически зависящий от пинга до интервала сервера, может быть примерно как 0,7,0,2 , 0,7). Я использую неблокирующие сокеты. Я попытался отключить алгоритм tgp nagle.Неблокирующие Winsockets C++ странные задержки

Вот код какого-то клиента:

memset(&hints, 0, sizeof hints); 
hints.ai_family = AF_UNSPEC; 
hints.ai_socktype = SOCK_STREAM; 
hints.ai_flags = AI_PASSIVE; 
int iStatus = getaddrinfo(Settings->GetDnSAddr().c_str(), 
Settings->GetPortStr().c_str(), &hints, &servinfo); 
if(iStatus != 0 || servinfo == NULL) 
{ 
    iState = L_CONNECT_DOWN; 
    throw ExeptionNetwork(903,__FILE__,__LINE__,iStatus); 
    return 0; 
} 

iSocketFD = socket(servinfo->ai_family,servinfo->ai_socktype,servinfo->ai_protocol); 
if (iSocketFD == INVALID_SOCKET) 
{ 
    THROWNETWORK(901); 
} 

cout<<"Connecting to server:"<<Settings->GetIPv4Addr()<<":"<<Settings->GetPort()<<endl; 
if (connect(iSocketFD,servinfo->ai_addr,servinfo->ai_addrlen) == SOCKET_ERROR) 
{ 
    cout<<"Connection failed:"<<errno<<endl; 
    iState = L_CONNECT_DOWN; 
    THROWNETWORK(902); 
    return 0; 
} 
cout<<"Connected"<<endl; 

#if (defined WIN32)||(defined WINCE) 
unsigned long iMode = 1; 
if (SOCKET_ERROR == ioctlsocket(iSocketFD, FIONBIO, &iMode)) 
{ 
    THROWNETWORK(903); 
} 
#else 
fcntl(iSocketFD, F_SETFL, O_NONBLOCK); 
#endif 


char flag =1; 
setsockopt(iSocketFD, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag)); 

Тогда читать я выглядывать с RECV(), и если есть что-то читать я читал.

Любые идеи? Может быть, так или иначе связано с вызовом recv? Я думаю о разделении кода сети на отдельный поток, возможно, это поможет ...

ответ

2

При работе с неблокирующими сокетами не используйте recv() для поиска байтов в поисках данных. Используйте select(), WSAAsyncSelect(), или WSAAsyncEvent(), чтобы получать уведомления о появлении данных, затем звоните recv(), чтобы прочитать его.

+0

Я уже пробовал использовать select и WSAPoll(), чтобы проверить, есть ли какие-то данные для чтения, но это не помогло. – Rulk

+0

Тогда вы не используете их правильно. Пожалуйста, покажите свой фактический код чтения. –

Смежные вопросы