私は2つのスレッドを持っています.1つはaccept()で新しい接続のためにブロックされ、もう1つは他のプロセスと話します. 私のアプリケーションがシャットダウンしようとしているとき、accept() から最初のスレッドを起動する必要があります。私はaccept()のmanページを読もうとしましたが、何かが完全に使用されていることがわかりませんでした. 私の質問は、2 番目のスレッドから最初のスレッドにどのシグナルを送信する必要があるかということです。
ありがとう。
私は2つのスレッドを持っています.1つはaccept()で新しい接続のためにブロックされ、もう1つは他のプロセスと話します. 私のアプリケーションがシャットダウンしようとしているとき、accept() から最初のスレッドを起動する必要があります。私はaccept()のmanページを読もうとしましたが、何かが完全に使用されていることがわかりませんでした. 私の質問は、2 番目のスレッドから最初のスレッドにどのシグナルを送信する必要があるかということです。
ありがとう。
タイムアウトでa を使用できますselect
。たとえば、実行中のスレッドaccept
は、何も起こらない場合は 1 ~ 2 秒ごとにウェイクアップし、シャットダウンをチェックします。このページをチェックして、アイデアを得ることができます。
「選択」を使用しない場合
サンプル コードは、Windows で非常にうまく機能しました。SIGINTを上げると「Exit」と表示されました。Linux に適したコードを編集できます。「closesocket」の代わりに「close」を使用し、winsock の開始に関するコードの最初の 2 行を削除し、Linux に必要なヘッダー ファイルを追加する必要があることを除いて、ほとんどすべてのソケット関数は同じです。
#include <stdio.h>
#include <winsock.h>
#include <signal.h>
#include <thread>
#pragma comment(lib,"wsock32.lib")
jmp_buf EXIT_POINT;
int sock,sockl=sizeof(struct sockaddr);
struct sockaddr_in xx,client;
int AcceptConnections = 1;
void _catchsignal(int signal)
{
closesocket(sock);
}
void thread_accept()
{
accept(sock,(struct sockaddr*)&client,&sockl);
}
void thread_sleep()
{
Sleep(1000);
raise(SIGINT);
}
int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsaData;
WSAStartup(MAKEWORD( 2, 2 ),&wsaData);
signal(SIGINT,_catchsignal);
xx.sin_addr.s_addr = INADDR_ANY;
xx.sin_family = AF_INET;
xx.sin_port = htons(9090);
sock = socket(AF_INET,SOCK_STREAM,0);
bind(sock,(struct sockaddr*)&xx,sizeof(struct sockaddr));
listen(sock,20);
std::thread th_accept(thread_accept);
std::thread th_sleep(thread_sleep);
th_accept.join();
th_sleep.join();
printf("Exit");
return 0;
}
まず、スレッドをブロックせずに受け入れ機能に「選択」機能を使用できます。msdnとbeejで select の詳細を学ぶことができます。私のお勧めは最後のものを見てください。Windows とほとんどのオペレーティング システムはほぼ同じ BSD ソケットで動作するため、ソケット プログラミングに MSDN リソースを使用できます。ブロックせずに接続を受け入れた後、ループを停止できるグローバル変数を定義するだけです。
私の英語で申し訳ありません。コード例を次に示します。
#include <stdio.h>
#include <stdlib.h>
#include <winsock.h>
#define DEFAULT_PORT 9090
#define QUEUE_LIMIT 20
int main()
{
WSADATA wsaData;
WSAStartup(MAKEWORD( 2, 2 ),&wsaData);
int ServerStream,SocketQueueMax=0,i,j,TMP_ClientStream;
int ClientAddrSize = sizeof(struct sockaddr),RecvBufferLength;
fd_set SocketQueue,SocketReadQueue,SocketWriteQueue;
struct sockaddr_in ServerAddr,TMP_ClientAddr;
struct timeval SocketTimeout;
char RecvBuffer[255];
const char *HelloMsg = "Connected.";
SocketTimeout.tv_sec = 1;
ServerAddr.sin_addr.s_addr = INADDR_ANY;
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons(DEFAULT_PORT);
ServerStream = socket(AF_INET,SOCK_STREAM,0);
bind(ServerStream,(struct sockaddr*)&ServerAddr,sizeof(struct sockaddr));
listen(ServerStream,QUEUE_LIMIT);
FD_ZERO(&SocketQueue);
FD_ZERO(&SocketReadQueue);
FD_ZERO(&SocketWriteQueue);
FD_SET(ServerStream,&SocketQueue);
SocketQueueMax = ServerStream;
bool AcceptConnections = 1;
while(AcceptConnections)
{
SocketReadQueue = SocketQueue;
SocketWriteQueue = SocketQueue;
select(SocketQueueMax + 1,&SocketReadQueue,&SocketWriteQueue,NULL,&SocketTimeout);
for(i=0;i < SocketQueueMax + 1;i++)
{
if(FD_ISSET(i,&SocketReadQueue))
{
if(i == ServerStream)
{
TMP_ClientStream = accept(ServerStream,(struct sockaddr*)&TMP_ClientAddr,&ClientAddrSize);
send(TMP_ClientStream,HelloMsg,strlen(HelloMsg),0);
FD_SET(TMP_ClientStream,&SocketQueue);
if(TMP_ClientStream > SocketQueueMax)
{
SocketQueueMax = TMP_ClientStream;
}
continue;
}
while((RecvBufferLength = recv(i,RecvBuffer,254,0)) > 0)
{
RecvBuffer[RecvBufferLength] = '\0';
for(j=0;j<SocketQueueMax + 1;j++)
{
if(j == i || j == ServerStream || !FD_ISSET(j,&SocketQueue))
{
continue;
}
send(j,RecvBuffer,RecvBufferLength + 1,0);
}
printf("%s",RecvBuffer);
if(RecvBufferLength < 254)
{
break;
}
}
}
}
}
return EXIT_SUCCESS;
}