Неблокирующие Winsockets c ++ странные задержки - PullRequest
0 голосов
/ 01 апреля 2012

Я портирую онлайн-игру с Linux на Windows. В Linux все прекрасно работает, но в Windows у меня странное поведение. Клиент и сервер общаются через постоянное TCP-соединение. Сервер отправляет пакет каждые 0,5 секунды. И в Linux я получаю пакет каждые 0,5 секунды, но в Windows у меня есть что-то вроде этого: 0,9,0.3,0.3,0.3,0.9 и т. Д. (Интервал на самом деле зависит от пинга до интервала сервера может быть что-то вроде 0,7,0.2 , 0,7). Я использую неблокирующие розетки. Я попытался отключить алгоритм tcp nagle.

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

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? Я думаю о разделении сетевого кода на отдельный поток, может быть, это поможет ...

1 Ответ

2 голосов
/ 01 апреля 2012

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

...