新しい接続のみを受け入れる 1 つのスレッドを作成することをお勧めします。そこにリスナーソケットがあります。次に、受け入れられるすべての接続に対して、新しい接続ソケットがあるため、別のスレッドを生成して、接続ソケットをパラメーターとして指定できます。そうすれば、接続を受け入れるスレッドはブロックされず、多くのクライアントに非常に高速に接続できます。処理スレッドはクライアントを処理し、終了します。
なぜそれらを待つ必要があるのか さえわかりませんが、そうする場合は、使用するOSやライブラリに応じて、他の方法で処理することができます(メッセージ、シグナルなどを使用できます)。
接続されたクライアントごとに新しいスレッドを生成したくない場合は、Ben Voigt が提案したように、select を使用できます。シングルスレッドにしたい場合、これは別の良いアプローチです。基本的に、すべてのソケットはソケット記述子の配列にあり、選択を使用すると、何が起こったのか (誰かが接続されている、ソケットが読み取り/書き込みの準備ができている、ソケットが切断されているなど) を知り、それに応じて動作します。
ここに 1 つの例を示します。部分的なものですが、機能します。acceptConnections() で接続を受け入れるだけで、クライアントごとに個別のスレッドが生成されます。そこでお客様とコミュニケーションを取ります。それは私が横たわっているWindowsコードからのものですが、どのプラットフォームでも再実装するのは非常に簡単です.
typedef struct SOCKET_DATA_ {
SOCKET sd;
/* other parameters that you may want to pass to the clientProc */
} SOCKET_DATA;
/* In this function you communicate with the clients */
DWORD WINAPI clientProc(void * param)
{
SOCKET_DATA * pSocketData = (SOCKET_DATA *)param;
/* Communicate with the new client, and at the end deallocate the memory for
SOCKET_DATA and return.
*/
delete pSocketData;
return 0;
}
int acceptConnections(const char * pcAddress, int nPort)
{
sockaddr_in sinRemote;
int nAddrSize;
SOCKET sd_client;
SOCKET sd_listener;
sockaddr_in sinInterface;
SOCKET_DATA * pSocketData;
HANDLE hThread;
sd_listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == sd_listener) {
fprintf(stderr, "Could not get a listener socket!\n");
return 1;
}
sinInterface.sin_family = AF_INET;
sinInterface.sin_port = nPort;
sinInterface.sin_addr.S_un.S_addr = INADDR_ANY;
if (SOCKET_ERROR != bind(sd_listener, (sockaddr*)&sinInterface, sizeof(sockaddr_in))) {
listen(sd_listener, SOMAXCONN);
} else {
fprintf(stderr, "Could not bind the listening socket!\n");
return 1;
}
while (1)
{
nAddrSize = sizeof(sinRemote);
sd_client = accept(sd_listener, (sockaddr*)&sinRemote, &nAddrSize);
if (INVALID_SOCKET == sd_client) {
fprintf(stdout, "Accept failed!\n");
closesocket(sd_listener);
return 1;
}
fprintf(stdout, "Accepted connection from %s:%u.\n", inet_ntoa(sinRemote.sin_addr), ntohs(sinRemote.sin_port));
pSocketData = (SOCKET_DATA *)malloc(sizeof(SOCKET_DATA));
if (!pSocketData) {
fprintf(stderr, "Could not allocate memory for SOCKET_DATA!\n");
return 1;
}
pSocketData->sd = sd_client;
hThread = CreateThread(0, 0, clientProc, pSocketData, 0, &nThreadID);
if (hThread == INVALID_HANDLE_VALUE) {
fprintf(stderr, "An error occured while trying to create a thread!\n");
delete pSocketData;
return 1;
}
}
closesocket(sd_listener);
return 0;
}