我有一個WinSock服務器設置,它正確接受客戶端並中繼相應的信息。服務器需要兩個客戶端,接收一個256字節的固定大小的緩衝區,將其存儲起來,然後將另一個緩衝區中繼給客戶端。 (即client1發送它的緩衝區,服務器保存它,然後向client1發送client2的緩衝區)。第一個客戶端在多路winsock服務器上是laggy
只要客戶端1更改其緩衝區,client2接收更改大約需要4秒鐘的時間。如果client2進行更改,client1幾乎立即收到更新(小於0.1s)。
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();
}
出於興趣,你怎麼沒有使用從套接字讀取的bBytes來決定你是否有一個完整的緩衝區?如果設置了WSAWOULDBLOCK,那麼這可能不是密鑰的大小?這是一段時間,但這似乎是錯誤的... – forsvarir 2011-04-04 21:32:44
我只是有nBytes變量設置做一些輸出,以確保我總是得到256字節,我是,所以我不認爲這是必要的檢查。 – 131nary 2011-04-04 21:39:13
您是否曾嘗試在recv + send的調用周圍添加記錄行,以便您知道服務器何時啓動/完成這些調用(這樣您就知道在哪裏花費時間)......在它的表面上,似乎您希望兩個緩衝區都能同時讀取某些內容... – forsvarir 2011-04-04 21:53:54