我应该使用哪个信号来接受accept()API?

时间:2013-07-17 12:53:53

标签: linux linux-kernel operating-system

我有两个线程,一个被阻塞,在accept()中有一个新连接,另一个线程正在处理其他进程。当我的应用程序要关闭时,我需要从accept()中唤醒第一个线程。我试图阅读accept()的手册页,但没有找到一些使用完整的东西。我的问题是我应该从第二个线程发送到第一个线程的哪个信号,这样它就会退出接受而且它也不会被杀死?

感谢。

2 个答案:

答案 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”函数来接受函数而不会阻塞线程。您可以在msdnbeej中了解有关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;
}