选择在 Windows 7 上无法正常工作

select doesn't works correctly on Windows 7

本文关键字:常工作 工作 Windows 选择      更新时间:2023-10-16

All:)

我有一些在Linux和WinXP上正确工作的代码

int FlowTestIP::do_recvfrom()
{
    int ret;
    struct timeval timeout;// = {2, 0};
    timeout.tv_sec = 2;
    timeout.tv_usec = 0;
    fd_set rfds;
    while(running) {
            FD_ZERO(&rfds);
            FD_SET(m_socket, &rfds);
            ret = select(m_socket + 1, &rfds, 0, 0, &timeout);
            cout << "// select ret = " << ret << " (errno = " << errno << ")" << endl;
            if (ret == -1 || ret == 0) {
                    if (!(ret == 0 && errno == 0))
                            cout << "select ret = " << ret << " (errno = " << errno << ")" << endl;
                    return ret;
            }
            if (FD_ISSET(m_socket, &rfds)) {
                    cout << WSAGetLastError() << endl;
                    break;
            }
    }
    return recvfrom(m_socket, in_buf, mtu, 0, (struct sockaddr *)&si_other, (socklen_t *)&otherAddrSize);
}

但是在Windows 7中,即使客户端应用程序退出,in也会继续循环。输出错误


…//select ret = 1 (errno = 0)
0
//select ret = 1 (errno = 0)
0
//select ret = 1 (errno = 0)
0
FTControlServerThread:运行
FTControlServerThread:收到
pkt->ft_tos = UCHAR_MAX
QFuture: waitForFinished ()
Client alive true
//select ret = 1 (errno = 0)
0
//select ret = 1 (errno = 0)
0
//select ret = 1 (errno = 0)
0

通常(在WinXP和Linux上)输出将是


…//select ret = 1 (errno = 0)
0
//select ret = 1 (errno = 0)
0
//select ret = 1 (errno = 0)
0
FTControlServerThread:运行
FTControlServerThread:收到
pkt->ft_tos = UCHAR_MAX
QFuture: waitForFinished ()
Client alive true
QFuture:完成了

这就是我所期待的。

有人遇到过这样的不当行为吗?

提前感谢!

注:@JoachimPileborg要求展示我如何调用这个函数:

FlowTest::recv(char *payload, size_t size)  
{  
...  
    while (running) {  
        len = do_recvfrom(); // it virtual method of class FlowTest  
        if (len == -1 || len == 0) {  
            return len;  
        }  
        if (running && !transport_recv_helper()) {  
            continue;  
        } else {  
            break;  
        }  
    }  
...  
}  

和从服务器GUI调用recv

void FlowTestServer::runTest(FlowTestServerHelper handler)
{
...
        if ((ret = server->recv(rcvdData, (size_t *)&size)) == -1 || ret == 0 || size == 0) {
            if (server_busy == 0)
                break;
            cout << "can't receive data (size == " << size << "; ret = " << ret << ")" << endl;
            continue;
        }
...
}

first:允许使用cout复位errno。它通常不这样做,但它可以,特别是在第一次使用时,它必须设置区域设置。您需要将errno的值保存在一个临时变量中,或者使用fprintf及其朋友-作为C库函数POSIX控制其行为。

其次:在Windows中,您需要使用WSAGetLastError()而不是errno

我建议你做一个宏sock_errno,在Linux/unix上是(errno),在Windows上是(WSAGetLastError())。这将使您能够以独立于平台的方式进行编码。

  • 查看更多信息:http://msdn.microsoft.com/en-us/library/windows/desktop/ms737828(v=vs.85).aspx