如何取消在Windows上的select()等待

Ser*_*kov 7 c++ sockets windows multithreading winsock

在我的程序中,有一个线程(接收线程)负责接收来自TCP套接字的请求,并且有许多线程(工作线程)负责处理接收到的请求.处理完请求后,我需要通过TCP发送答案.

这是一个问题.我想在用于接收数据的同一个线程中发送TCP数据.接收数据后,此线程通常会等待新数据select().因此,一旦工作线程完成处理请求并将答案放入输出队列,它就必须通知接收线程有数据要发送.问题是我不知道如何取消等待select()以便离开等待和打电话send().

或者我是否应该仅使用另一个线程通过TCP发送数据?

更新

MSalters,Artyom谢谢你的答案!

MSalters,看了你的答案,我发现这个网站:Winsock 2 I/O方法和阅读WSAWaitForMultipleEvents().我的程序实际上必须在HP-UX和Windows上工作我最终决定使用Artyom建议的方法.

Art*_*yom 16

您需要使用类似于safe-pipe技巧的东西,但在您的情况下,您需要使用一对连接的TCP套接字.

  1. 创建一对套接字.
  2. 添加一个到选择并等待它
  3. 通过从其他线程写入其他套接字来通知.
  4. 当一个套接字可读时,选择立即被唤醒,读取此特殊套接字中的所有数据并检查队列中的所有数据以发送/恢复

如何在Windows下创建一对套接字?

inline void pair(SOCKET fds[2])
{
    struct sockaddr_in inaddr;
    struct sockaddr addr;
    SOCKET lst=::socket(AF_INET, SOCK_STREAM,IPPROTO_TCP);
    memset(&inaddr, 0, sizeof(inaddr));
    memset(&addr, 0, sizeof(addr));
    inaddr.sin_family = AF_INET;
    inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    inaddr.sin_port = 0;
    int yes=1;
    setsockopt(lst,SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(yes));
    bind(lst,(struct sockaddr *)&inaddr,sizeof(inaddr));
    listen(lst,1);
    int len=sizeof(inaddr);
    getsockname(lst, &addr,&len);
    fds[0]=::socket(AF_INET, SOCK_STREAM,0);
    connect(fds[0],&addr,len);
    fds[1]=accept(lst,0,0);
    closesocket(lst);
}
Run Code Online (Sandbox Code Playgroud)

当然,应该为返回值添加一些检查.

  • 你真的不需要一对套接字,你可以使用一个"连接"自己的UDP套接字. (2认同)

MSa*_*ers 7

select不是Windows的本机API.原生方式是WSAWaitForMultipleEvents.如果使用此命令创建可警告的等待,则可以使用QueueUserAPC指示等待的线程发送数据.(这也可能意味着您不必实现自己的输出队列)