首页 > 解决方案 > 一个线程全部退出

问题描述

我有一个生成几个线程的主程序(使用带有accept()的while循环来获取客户端),它所要做的就是“听键盘”,当用户输入单词退出时它会关闭整个程序。首先,主程序创建监听线程,然后进入接受客户端的while循环。即使侦听线程获得退出输入,循环仍然停留在接受状态。

我不必使用单独的线程来听键盘,但我找不到可行的无阻塞方式。

听力线程:

DWORD WINAPI ListenService(LPVOID lpParam)
{
    char buffer[5];
    if (EOF == scanf("%s", buffer))
    {
        printf("faile get word from keyboard\n");
    }
    if (buffer[4] != '\0')
        strcat(buffer, "\0");
    if (STRINGS_ARE_EQUAL(buffer, "exit"))
    {
        return 999;
    }
    return -1;
}

在主代码中:

ThreadListen = CreateThread(NULL,0,ListenService,NULL,0,&(ThreadId));   
while(1)
{
    SOCKET AcceptSocket = accept(MainSocket, NULL, NULL);
    if (AcceptSocket == INVALID_SOCKET)
    {
        printf("Accepting connection with client failed, error %ld\n", WSAGetLastError());
        CleanupWorkerThreads();
        WSACleanup();
    }
    printf("Client Connected.\n");
}

标签: cmultithreadingsocketswinapi

解决方案


有许多不同的方法可以处理这个问题。

accept()您可以通过简单地关闭侦听套接字来中止阻塞。

或者,您可以使用select()短暂的超时来检测新客户端何时在调用之前等待accept()。您可以在两次调用之间检查退出条件select()。请注意,有一个小的竞争条件,客户端可能会在时间之间断开连接select()并被accect()调用,因此如果没有更多客户端等待,accept() 可能仍会阻塞。

或者,您可以摆脱线程,只在单个线程中使用非阻塞套接字,在套接字操作之间定期检查退出条件。

或者,您可以使用异步套接字,使用WSACreateEvent()WSAEventSelect()WSAWaitForMultipleEvents()来检测套接字活动。然后,您可以创建一个添加事件以等待退出条件发生。

或者,您可以使用 I/O 完成端口来处理套接字活动,然后您可以将自定义退出数据包发布到 IOCP 队列中PostQueuedCompletionStatus(),以“唤醒”任何等待线程。


推荐阅读