【问题标题】:Set a timeout for recv from socket on Windows从 Windows 上的套接字为 recv 设置超时
【发布时间】:2016-09-07 16:52:33
【问题描述】:

嗯, 我认为我的代码是正确的,但它不起作用:(

要在 Windows 上为 recv 函数设置超时,我知道我必须使用此代码:

                    DWORD timeout = 2000;

                 if (setsockopt(listenSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(DWORD)))
                 { perror("setsockopt");
                return -1;
                 }

但它不起作用。

我的服务器的代码是:

    SOCKET listenSocket;
SOCKET remoteSocket= INVALID_SOCKET;
SOCKADDR_IN Server_addr;
SOCKADDR_IN Client_addr;
int sin_size;
short port;

int wsastartup;
int ls_result;
WORD wVersionRequested = 0x0202;
WSADATA wsaData;

wsastartup = WSAStartup(wVersionRequested, &wsaData);
if (wsastartup != NO_ERROR) cout << "Errore WSAStartup()" << endl;

listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

port = 4000;
Server_addr.sin_family = AF_INET;
Server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

Server_addr.sin_port = htons(port);

if (bind(listenSocket,(LPSOCKADDR) &Server_addr,sizeof(struct sockaddr)) < 0) {
    cout << "Server: error bind." << endl;
closesocket(listenSocket);
return -1;
}

ls_result = listen(listenSocket, SOMAXCONN);

sin_size = sizeof(struct sockaddr_in);
remoteSocket = accept(listenSocket, (struct sockaddr *) &Client_addr, &sin_size);

// SET THE TIME OUT
DWORD timeout = 300;
if (setsockopt(remoteSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(DWORD)))
{ perror("setsockopt");
    return -1;
}

int i=0;
while (i<50){
    t_start = clock();

    // when client receives the send below it wait 3 seconds and then trasmits the answer
    send(remoteSocket, "code of start transmission", sizeof("code of start transmission"), 0);

    recv_size=recv(remoteSocket, messaggio, sizeof(messaggio), 0);

    printf("time for read=  %f second \n", ((double)(end - t_start)) / CLOCKS_PER_SEC);

    i=i+1;
}

客户端收到服务器发来的“开始传输代码”消息后,等待3秒后向服务器发送请求。 我预计读取时间为 300 毫秒且 recv_size

我在 Windows 上,我正在使用 eclipse 和 mingw-w64。

有人可以帮帮我吗??

【问题讨论】:

    标签: c++ sockets winsock


    【解决方案1】:

    您的代码在超时后尝试使用套接字。这不是一个好主意,因为套接字仍然处于失败的阻塞操作的中间,并且无法启动新的操作。无法展开先前完成的操作部分并将套接字放回操作开始之前的位置。

    一旦阻塞套接字操作超时,您所能做的就是关闭套接字。不支持撤消部分完成的操作并使套接字处于任何正常状态。

    如果套接字上的发送或接收操作超时,则套接字状态是不确定的,不应使用[.] -- MSDN

    SO_RCVTIMEO 套接字选项永远不应在设计用于套接字的代码中使用。防止代码中的无限等待是一种杂乱无章的做法,而这些代码并非旨在与本机套接字一起使用。这些不是您要寻找的机器人。

    【讨论】:

    • 感谢您的回答。我会根据您的评论修改我的代码。
    【解决方案2】:

    要在 Windows 上为 recv 函数设置超时,我知道我必须使用此代码:

                 DWORD timeout = 2000;
    
                 if (setsockopt(listenSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(DWORD)))
                 { perror("setsockopt");
                return -1;
                 }
    

    没有。它应该是int,而不是DWORD,但主要问题是您在这里设置了accept() 超时,因为这是监听套接字。您需要在接受的套接字上设置它。

    【讨论】:

    • 我相信几乎所有现代实现都继承了它。但我肯定会尝试在单个套接字上设置它以确保它没有很好的记录。
    • 在 Windows 上,它绝对应该是 DWORD,而不是 intMSDN documentation 说了很多。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-04
    相关资源
    最近更新 更多