我有两个线程,一个被阻塞,在accept()中有一个新连接,另一个线程正在处理其他进程。当我的应用程序要关闭时,我需要从accept()中唤醒第一个线程。我试图阅读accept()的手册页,但没有找到一些使用完整的东西。我的问题是我应该从第二个线程发送到第一个线程的哪个信号,这样它就会退出接受而且它也不会被杀死?
感谢。
答案 0 :(得分:2)
你可以使用带有超时的select
,例如,如果没有任何事情发生,你的线程执行accept
每1或2秒唤醒一次,并检查是否关闭。您可以查看this page以了解相关信息。
答案 1 :(得分:0)
不使用“选择”
示例代码在Windows上运行良好。当SIGINT引发时,它显示“退出”。您可以编辑适合Linux的代码。几乎每个套接字函数都是相同的,除了你应该使用“close”而不是“closesocket”,你应该删除前两行代码,它是关于启动winsock并为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;
}
首先,您可以使用“select”函数来接受函数而不会阻塞线程。您可以在msdn和beej中了解有关select的更多信息,我的建议是查看最后一个,您可以在套接字编程上使用MSDN资源,因为Windows和大多数操作系统都在BSD套接字上工作,这几乎完全相同。接受连接而不阻塞它们之后,您可以定义一个可以停止循环的全局变量。
对不起我的英文,这是一个示例代码:
#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;
}