第一个客户端在多套接字winsock服务器中滞后
我有一个 WinSock 服务器设置,它可以正确接受客户端并转发适当的信息。服务器接收两个客户端,接收 256 字节的固定大小缓冲区,存储它,然后将另一个缓冲区中继到客户端。 (即客户端1发送其缓冲区,服务器保存它,然后将客户端2的缓冲区发送给客户端1)。
每当 client1 更改其缓冲区时,client2 大约需要 4 秒才能收到更改。如果 client2 进行更改,client1 几乎立即收到更新(不到 0.1 秒)。
Nagle 的算法被禁用,我尝试更改服务器处理请求的顺序,但 client1 总是滞后。数据总是完好无损地显示,但时间太长。下面是服务器处理数据的循环:
for(;;)
{
// check if more clients can join
if (numClients < MAX_CLIENTS)
{
theClients[numClients] = accept(listeningSocket, NULL, NULL);
if (theClients[numClients] == INVALID_SOCKET)
{
nret = WSAGetLastError();
JBS::reportSocketError(nret, "server accept()");
closesocket(listeningSocket);
WSACleanup();
exit(0);
}
// disable Nagle's algorithm
int flag = 1;
int result = setsockopt(theClients[numClients], IPPROTO_TCP, TCP_NODELAY,
(char *) &flag, sizeof(int));
if (result < 0)
{
nret = WSAGetLastError();
JBS::reportSocketError(nret, "client connect()");
closesocket(theClients[numClients]);
WSACleanup();
}
// make the socket non-blocking
u_long iMode = 1;
ioctlsocket(theClients[numClients],FIONBIO, &iMode);
cout << "Client # " << numClients << " connected." << endl;
numClients++;
started = true;
}
else
{
// we've received all the connections, so close the listening socket
closesocket(listeningSocket);
}
// process client2
if (theClients[1] != INVALID_SOCKET)
{
memset(keys2, 0, 255);
// receive the updated buffer
nBytes = recv(theClients[1], keys2, sizeof(keys2), 0);
receiveResult = WSAGetLastError();
if ((receiveResult != WSAEWOULDBLOCK) && (receiveResult != 0))
{
JBS::reportSocketError(receiveResult, "server receive keys2()");
shutdown(theClients[1],2);
closesocket(theClients[1]);
WSACleanup();
exit(0);
break;
}
// send client1's buffer to client2
send(theClients[1],keys1,sizeof(keys1),0);
sendResult = WSAGetLastError();
if((sendResult != WSAEWOULDBLOCK) && (sendResult != 0))
{
JBS::reportSocketError(sendResult, "server send keys1()");
shutdown(theClients[1],2);
closesocket(theClients[1]);
WSACleanup();
exit(0);
break;
}
}
// process client1
if (theClients[0] != INVALID_SOCKET)
{
memset(keys1, 0, 255);
// receive the updated buffer
nBytes = recv(theClients[0], keys1, sizeof(keys1), 0);
receiveResult = WSAGetLastError();
if ((receiveResult != WSAEWOULDBLOCK) && (receiveResult != 0))
{
JBS::reportSocketError(receiveResult, "server receive keys1()");
shutdown(theClients[0],2);
closesocket(theClients[0]);
WSACleanup();
exit(0);
break;
}
// send client2's buffer to client1
send(theClients[0],keys2,sizeof(keys2),0);
sendResult = WSAGetLastError();
if((sendResult != WSAEWOULDBLOCK) && (sendResult != 0))
{
JBS::reportSocketError(sendResult, "server send keys2()");
shutdown(theClients[0],2);
closesocket(theClients[0]);
WSACleanup();
exit(0);
break;
}
}
Sleep((float)(1000.0f / 30.0f));
}
客户端发送代码:
int nError, sendResult;
sendResult = send(theSocket, keys, sizeof(keys),0);
nError=WSAGetLastError();
if((nError != WSAEWOULDBLOCK) && (nError != 0))
{
JBS::reportSocketError(sendResult, "client send()");
shutdown(theSocket,2);
closesocket(theSocket);
WSACleanup();
}
I have a WinSock server setup, which is properly accepting clients and relaying the appropriate information. The server takes two clients, receives a fixed size buffer of 256 bytes, stores it, and then relays the other buffer to the client. (Ie. client1 sends its buffer, server saves it, then sends client1 the buffer for client2).
Anytime client1 changes its buffer, it takes roughly 4 seconds for client2 to receive the changes. If client2 makes a change, client1 receives the update almost instantly (less than 0.1s).
Nagle's algorithm is disabled and I've tried changing the order which the server processes the requests, but client1 always lags. The data always shows up intact, but takes too long. Below is the loop the server uses to process the data:
for(;;)
{
// check if more clients can join
if (numClients < MAX_CLIENTS)
{
theClients[numClients] = accept(listeningSocket, NULL, NULL);
if (theClients[numClients] == INVALID_SOCKET)
{
nret = WSAGetLastError();
JBS::reportSocketError(nret, "server accept()");
closesocket(listeningSocket);
WSACleanup();
exit(0);
}
// disable Nagle's algorithm
int flag = 1;
int result = setsockopt(theClients[numClients], IPPROTO_TCP, TCP_NODELAY,
(char *) &flag, sizeof(int));
if (result < 0)
{
nret = WSAGetLastError();
JBS::reportSocketError(nret, "client connect()");
closesocket(theClients[numClients]);
WSACleanup();
}
// make the socket non-blocking
u_long iMode = 1;
ioctlsocket(theClients[numClients],FIONBIO, &iMode);
cout << "Client # " << numClients << " connected." << endl;
numClients++;
started = true;
}
else
{
// we've received all the connections, so close the listening socket
closesocket(listeningSocket);
}
// process client2
if (theClients[1] != INVALID_SOCKET)
{
memset(keys2, 0, 255);
// receive the updated buffer
nBytes = recv(theClients[1], keys2, sizeof(keys2), 0);
receiveResult = WSAGetLastError();
if ((receiveResult != WSAEWOULDBLOCK) && (receiveResult != 0))
{
JBS::reportSocketError(receiveResult, "server receive keys2()");
shutdown(theClients[1],2);
closesocket(theClients[1]);
WSACleanup();
exit(0);
break;
}
// send client1's buffer to client2
send(theClients[1],keys1,sizeof(keys1),0);
sendResult = WSAGetLastError();
if((sendResult != WSAEWOULDBLOCK) && (sendResult != 0))
{
JBS::reportSocketError(sendResult, "server send keys1()");
shutdown(theClients[1],2);
closesocket(theClients[1]);
WSACleanup();
exit(0);
break;
}
}
// process client1
if (theClients[0] != INVALID_SOCKET)
{
memset(keys1, 0, 255);
// receive the updated buffer
nBytes = recv(theClients[0], keys1, sizeof(keys1), 0);
receiveResult = WSAGetLastError();
if ((receiveResult != WSAEWOULDBLOCK) && (receiveResult != 0))
{
JBS::reportSocketError(receiveResult, "server receive keys1()");
shutdown(theClients[0],2);
closesocket(theClients[0]);
WSACleanup();
exit(0);
break;
}
// send client2's buffer to client1
send(theClients[0],keys2,sizeof(keys2),0);
sendResult = WSAGetLastError();
if((sendResult != WSAEWOULDBLOCK) && (sendResult != 0))
{
JBS::reportSocketError(sendResult, "server send keys2()");
shutdown(theClients[0],2);
closesocket(theClients[0]);
WSACleanup();
exit(0);
break;
}
}
Sleep((float)(1000.0f / 30.0f));
}
Client sending code:
int nError, sendResult;
sendResult = send(theSocket, keys, sizeof(keys),0);
nError=WSAGetLastError();
if((nError != WSAEWOULDBLOCK) && (nError != 0))
{
JBS::reportSocketError(sendResult, "client send()");
shutdown(theSocket,2);
closesocket(theSocket);
WSACleanup();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我已将您的代码粘贴在下面,其中包含一些内联注释,主要是因为我无法将其全部合理地放入注释中。您如何确定从 client1 到 client2 的更改需要四秒钟?目视检查?这是否意味着 Client1 & Client2 在同一台机器上运行(无需担心不同的网络延迟问题)?
我突出显示了一些看起来错误的块。它们可能不是,这可能是因为您尝试简化您发布的代码并且错过了一些位。我还针对您可能想要添加一些日志记录的位置提出了一些建议。如果套接字确实是非阻塞的,那么您应该很快从所有调用中返回并且无法读取数据,除非客户端已发送数据。如果您有 4 秒的延迟,那么问题可能是:
掌握每段代码所花费的时间将有助于找出问题所在。
您可以使用类似以下内容(从网络借用)来获取时间:
您的代码:
客户端发送代码:
I've pasted your code below, with some inline comments in it, mostly because I can't fit it all reaonsably in a comment. How are you determining that it's taking four seconds for changes to get from client1 to client2? Visual inspection? Does this mean that Client1 & Client2 are running on the same machine (no different network latency issues to worry about)?
I've highlighted some blocks that look wrong. They may not be, it may be because you've tried to simplify the code that you've posted and you've missed some bits. I've also made some suggestions for where you might want to add some logging. If the sockets are really non-blocking you should be coming back from all of the calls very quickly and failing to read data, unless the client has sent it. If you've got a 4 second delay, then the problem could be:
Having the times each section of code takes will help to track down where your problem is.
You can get the time, using something like this (borrowed from the web):
Your code:
Client sending code: