【问题标题】:Interrupt a receiving socket中断接收套接字
【发布时间】:2012-08-01 20:33:20
【问题描述】:

我有一个 WinSock mySocket,它像这样在循环中接收:

while(keepGoing){
    FD_SET fsd;
    FD_ZERO(&fds);
    FD_SET(mySocket, &fds);

    int result = select(1+mySocket, &fds, (fd_set *)0, (fd_set *)0, &timeout);
    if(result>0 && FD_ISSET(mySocket, &fds){
        result = recvfrom(mySocket, buff, NUM_BYTES, (struct sockaddr *)&add, &length);
        // do stuff       
    }
}

如果我想停止接收,我可以将 keepGoing 设置为 false,但套接字可能仍在等待 timeout,然后才能看到 keepGoing 已更改。

假设我们不想改变超时的值,有没有可靠的方法告诉套接字停止接收而不等待超时发生?

【问题讨论】:

    标签: c++ sockets timeout winsock


    【解决方案1】:

    errnoEINTR 时,您可以发出良性信号并检查keepGoing 标志。或者,您可以创建一个pipe 并将读取端添加到您的select 集中。设置keepGoing标志后关闭写端。

    int quitfds[2];
    pipe(quitfds);
    
        //...
        FD_SET(quitfds[0], &fds);
        //...
    
        if (FD_ISSET(quitfds[0], &fds)) {
            close(quitfds[0]);
            continue;
        }
    

    编辑: Adam 指出我错过了问题中的 Winsock 引用。您可以使用socketpair 而不是pipe。它似乎没有在 Windows 上实现,但我找到了a workaround here。 Ben 指出WSAEventSelect 允许混合不同的事件对象。感谢两者。

    【讨论】:

    • 这对 Unix 来说很好,但是 Windows 没有信号,而且 WinSock 的select 实现只能处理套接字对象,不能处理管道等其他类型的文件类对象。
    • @Adam:select 是正确的,但 Windows 也有 WSAEventSelect,它确实启用了混合。
    • @Adam:感谢您向我指出这一点,我在问题中错过了这一点。
    • @Ben:哦,好点,我不知道WSAEventSelect
    • 如果是 TCP 并且您已经完全完成了套接字,请将其关闭以进行输入。这将为recv() 方法提供一个流结束(返回值为零)。您仍然可以写入套接字。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-12
    • 1970-01-01
    • 2019-03-05
    • 2011-08-06
    • 2012-03-08
    相关资源
    最近更新 更多