Linux 我应该使用哪个信号来输出accept()API?

Linux 我应该使用哪个信号来输出accept()API?,linux,linux-kernel,operating-system,Linux,Linux Kernel,Operating System,我有两个线程,一个在accept()中为新连接而被阻止,另一个在与其他进程对话。当我的应用程序即将关闭时,我需要从accept()中唤醒第一个线程。我试图阅读accept()的手册页,但没有发现有什么东西可以完全使用。我的问题是,我应该从第二个线程向第一个线程发送哪个信号,这样它就会从accept中出来,并且不会被杀死 谢谢 您可以使用带有超时的选择,例如,如果没有发生任何情况,则执行接受的线程每1或2秒唤醒一次,并检查是否关闭。您可以查看以获得想法。无需使用“选择” 示例代码在Windows上

我有两个线程,一个在accept()中为新连接而被阻止,另一个在与其他进程对话。当我的应用程序即将关闭时,我需要从accept()中唤醒第一个线程。我试图阅读accept()的手册页,但没有发现有什么东西可以完全使用。我的问题是,我应该从第二个线程向第一个线程发送哪个信号,这样它就会从accept中出来,并且不会被杀死


谢谢

您可以使用带有超时的
选择
,例如,如果没有发生任何情况,则执行
接受
的线程每1或2秒唤醒一次,并检查是否关闭。您可以查看以获得想法。

无需使用“选择”

示例代码在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;
}
#包括
#包括
#包括
#包括
#pragma注释(lib,“wsock32.lib”)
jmp_buf出口_点;
int sock,sockl=sizeof(struct sockaddr);
xx中的结构sockaddr_,客户端;
int=1;
无效信号(内部信号)
{
插座;
}
无效线程\u接受()
{
接受(sock,(struct sockaddr*)和客户机,&sockl);
}
无效线程_sleep()
{
睡眠(1000);
升起(SIGINT);
}
int _tmain(int argc,_TCHAR*argv[]
{
WSADATA WSADATA;
WSAStartup(MAKEWORD(2,2)和wsaData);
信号(SIGINT,_catchsignal);
xx.sin_addr.s_addr=INADDR\u ANY;
xx.sin_family=AF_INET;
xx.sinu端口=htons(9090);
sock=socket(AF\u INET,sock\u STREAM,0);
绑定(sock,(struct sockaddr*)和xx,sizeof(struct sockaddr));
听(索克,20);
std::线程THU accept(线程THU accept);
标准:线程睡眠(线程睡眠);
接受。加入();
你睡觉吧,加入;
printf(“退出”);
返回0;
}

首先,您可以使用“选择”函数来接受函数,而不阻塞线程。您可以了解有关select in的更多信息,我的建议是查看最后一个,您可以在套接字编程上使用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;
}
#包括
#包括
#包括
#定义默认的\u端口9090
#定义队列限制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_设置SocketQueue、SocketReadQueue、SocketWriteQueue;
ServerAddr、TMP\u ClientAddr中的结构sockaddr\u;
结构timeval SocketTimeout;
char RecvBuffer[255];
const char*HelloMsg=“已连接。”;
SocketTimeout.tv_sec=1;
ServerAddr.sin\u addr.s\u addr=INADDR\u ANY;
ServerAddr.sin_family=AF_INET;
ServerAddr.sin\u port=htons(默认\u端口);
ServerStream=socket(AF\u INET,SOCK\u STREAM,0);
绑定(ServerStream,(struct sockaddr*)&ServerAddr,sizeof(struct sockaddr));
侦听(服务器流、队列限制);
FD_ZERO(&SocketQueue);
FD_ZERO(&SocketReadQueue);
FD_ZERO(和SocketWriteQueue);
FD_集(服务器流和SocketQueue);
SocketQueueMax=ServerStream;
bool-AcceptConnections=1;
while(接受连接)
{
SocketReadQueue=SocketQueue;
SocketWriteQueue=SocketQueue;
选择(SocketQueueMax+1,&SocketReadQueue,&SocketWriteQueue,NULL,&SocketTimeout);
对于(i=0;iSocketQueueMax)
{
SocketQueueMax=TMP_客户端流;
}
继续;
}
而((RecvBufferLength=recv(i,RecvBuffer,254,0))>0)
{
RecvBuffer[RecvBufferLength]='\0';

对于(j=0;jj)是的,但这会使我的代码更复杂,在poll和select之间哪一个更好?我想你是“SIGINT”,它被描述为“交互式注意信号”但在signal函数结束后,程序返回到它离开的地方。据我所知,signal将中断主线程而不是子线程。您可以使用pthread_kill向特定线程发送信号,SIGINT的默认操作是kill:)。我不想要,即使我按照你说的处理这个信号,程序也会回到原来的位置:(@AmitBhaira你试过使用“goto”吗?我知道它不漂亮,但它一定能工作。??我没明白你的意思!!我编辑了我的答案,我写了一个代码,没有使用“select”,我用“SIGINT”关闭套接字。