简体   繁体   English

在Windows上为套接字设置recv的超时

[英]Set a timeout for recv from socket on Windows

Ih, I think my code is correct but it doesn't work :( 嗯,我认为我的代码是正确的,但它不起作用:(

To set a timeout for recv function on windows i know i must use this code: 要在Windows上为recv函数设置超时,我知道我必须使用以下代码:

                    DWORD timeout = 2000;

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

But it doesn't work. 但它不起作用。

The code of my server is: 我的服务器的代码是:

    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;
}

The client when receives the message "code of start transmission" from servers, it wait 3 seconds and then aswer to server. 客户端从服务器收到消息“启动传输代码”时,等待3秒然后再向服务器发送。 I expect time for read is 300 ms and recv_size<0, instead recv_size<0 but time for read is more or less 1.5 seconds (The server waits for the client's message). 我希望读取的时间是300毫秒,recv_size <0,而不是recv_size <0,但读取时间大约是1.5秒(服务器等待客户端的消息)。 I don't understand why. 我不明白为什么。

I'm on windows and i'm using eclipse and mingw-w64. 我在窗户上,我正在使用eclipse和mingw-w64。

Please someone can help me?? 请有人可以帮帮我吗?

Your code tries to use the socket after it has timed out. 您的代码在超时后尝试使用套接字。 This is not a good idea because the socket is still somewhere in the middle of the failed blocking operation and in no shape to start a new operation. 这不是一个好主意,因为套接字仍处于失败阻塞操作的中间位置,并且无法启动新操作。 There's no way to unwind the portions of the operation that have previously completed and put the socket back where it was before the operation started. 没有办法解开先前已完成的操作部分,并将套接字放回操作开始之前的位置。

Once a blocking socket operation times out, all you can safely do is close the socket. 阻塞套接字操作超时后,您可以放心地关闭套接字。 There is no support for undoing an operation that is partially completed and leaving the socket in any kind of sane state. 不支持撤消部分完成的操作并使套接字处于任何类型的健全状态。

If a send or receive operation times out on a socket, the socket state is indeterminate, and should not be used[.] -- MSDN 如果发送或接收操作在套接字上超时,套接字状态是不确定的,不应该使用[。] - MSDN

The SO_RCVTIMEO socket option should never be used in code that's designed to work with sockets. 绝不应在设计用于套接字的代码中使用SO_RCVTIMEO套接字选项。 It's a kludge to prevent infinite waits in code that wasn't designed to work with sockets natively. 这是一个防止代码无限等待的原因,这些代码本身并不适用于套接字。 These aren't the droids you're looking for. 这些不是您正在寻找的机器人。

To set a timeout for recv function on windows i know i must use this code: 要在Windows上为recv函数设置超时,我知道我必须使用以下代码:

             DWORD timeout = 2000;

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

No. It should be an int , not a DWORD , but the main problem is that youre are here setting an accept() timeout, as this is the listening socket. 不。它应该是一个int ,而不是一个DWORD ,但主要的问题是你在这里设置一个accept()超时,因为这是监听套接字。 You need to set it on the accepted socket(s). 您需要在接受的套接字上设置它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM