2016-09-07 6 views
1

1H、 にソケットからのrecvのタイムアウトを設定し、私は私のコードが正しいことだと思うが、それは、私はこのコードを使用する必要があります知っている窓にrecv関数のタイムアウトを設定するには:(は、Windows

を動作しません。 。

    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秒待ってからサーバに転送します。 read時間が300ms、recv_sizeが<で、recv_sizeが<で0ですが、読み取り時間が1.5秒(サーバーがクライアントのメッセージを待っています)です。なぜか分からない。

私は窓があり、私はeclipseとmingw-w64を使用しています。

誰かが私を助けることができますか?私はこのコードを使用する必要があります知っている窓にrecv関数のタイムアウトを設定するには

答えて

1

   DWORD timeout = 2000; 

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

いいえそれはint、ないDWORDにする必要がありますが、主な問題は、ということですここではリッスンソケットなので、accept()タイムアウトを設定しています。受け入れられたソケットに設定する必要があります。

+0

私はこれが、ほとんど全ての現代的な実装で受け継がれていると信じています。しかし、私は間違いなく個々のソケットにそれを設定しようとしています、それは十分に文書化されていません。 –

+0

Windowsでは、間違いなく 'int 'ではなく' DWORD'でなければなりません。 [MSDNのドキュメント](https://msdn.microsoft.com/en-us/library/windows/desktop/ms740532.aspx)には多くのことが書かれています。 –

1

あなたのコードは、タイムアウトした後にソケットを使用しようとします。これは良い考えではありません。なぜなら、ソケットはまだ失敗したブロッキング操作の途中であり、新しい操作を開始するための形をしていないからです。前に完了した操作の部分を巻き戻して、操作を開始する前の位置にソケットを戻す方法はありません。

ブロッキングソケット操作がタイムアウトすると、安全に行うことができるのはソケットを閉じることだけです。部分的に完了した操作を元に戻したり、ソケットを正常な状態にすることはできません。

ソケット上で動作時間を受信、送信または場合は、ソケットの状態は不確定で、かつ使用すべきではない[。] - MSDN

SO_RCVTIMEOのソケットオプションがで使用すべきではありませんソケットで動作するように設計されたコード。これは、ソケットでネイティブに動作するように設計されていないコードの無限の待機を防ぐためのものです。これらはあなたが探しているドロイドではありません。

+0

答えをありがとう。あなたのコメントを考慮してコードを修正します。 – cerry92