3000 以上の接続を処理する必要があるゲームサーバー (TCP) を作成しています。現在、50 の接続があり、既に遅延が発生しています。
winsock send() 呼び出しが返されるのにそれぞれ約100〜300ミリ秒かかることがわかりました。これは、シングルスレッドサーバーであるため、サーバー全体の速度がかなり低下します。
これまでのところ、私は2つの解決策について考えてきました。
- クライアントごとにスレッドを作成するようにサーバーを再設計します (3000 クライアントに対して 3000 以上のスレッドを作成するのは本当に安定していますか?)。
- send() 呼び出しをすぐに返す方法を見つけてください。
これは私のソケットの初期化コードです:
int ret = WSAStartup(MAKEWORD(2,2), &wsaData);
if(ret != 0)
{
printf("Winsock failed to start.\n");
system("pause");
return;
}
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(52000);
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock == INVALID_SOCKET)
{
printf("Invalid Socket.\n");
system("pause");
return;
}
if(bind(sock, (sockaddr*)&server, sizeof(server)) != 0)
{
printf("error");
return;
}
if(listen(sock, 5) != 0)
{
printf("error");
return;
}
別のスレッドでコードを受け入れる
sockaddr_in from;
int fromlen = sizeof(from);
SOCKET sTmpSocket = accept(ServerSock, (struct sockaddr*)&from, &fromlen);
私の送信機能
void CClient::SendPacket(BYTE* pPacket, DWORD Len)
{
DWORD ToSendLen = Len;
while (ToSendLen)
{
int iResult = send(this->ClientSocket, (char*)(pPacket + Len - ToSendLen), ToSendLen, 0);
if (iResult == SOCKET_ERROR)
return;
ToSendLen -= iResult;
}
}
これは私のサーバー スレッドです (不完全、関連部分のみ)
while (1)
{
for (int i = 0; i < MAX_CLIENT; i++)
{
if (Clients[i].bConnected == false)
continue;
timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 1;
fd_set socketset;
socketset.fd_count = 1;
socketset.fd_array[0] = Clients[i].ClientSocket;
if (select(0, &socketset, 0, 0, &timeout))
{
int RecvLen = recv(Clients[i].ClientSocket, (char*)pBuffer, 10000, MSG_PEEK);
if (RecvLen == SOCKET_ERROR)
{
Clients[i].bConnected = false;
iNumClients--;
}
else if (RecvLen == 0)
{
Clients[i].bConnected = false;
iNumClients--;
}
else if (RecvLen > 0)
{
// Packet handling here
recv(Clients[i].ClientSocket, (char*)pBuffer, dwDataLen, MSG_WAITALL);
//...
}
}
}
Sleep(1);
}
どんな助けでも大歓迎です。ありがとうございました。