2016-04-28 19 views
-1

ソケットがタイムアウトしたかどうか、またはそれ以上のデータがない場合はどうすれば認識できますか?TCPソケットのタイムアウトまたは読み取るデータがありません

私はこれを持っている:

EWOULDBLOCKまたは EAGAINが設定されている場合、私はチェックしますが、タイムアウトが発生しなかった場合でも、彼らは設定された後
setsockopt(cli_socket, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv, sizeof(struct timeval)); //5 sec timeout 
while(1) 
{ 
    l = recv(socket, ...); 
    if(l < 0) 
    break; 
} 

。接続がタイムアウトしたか、正常に読み込まれたかによって、別のアクションを実行する必要があります。

+0

"タイムアウトが発生しなくても設定されています"とはどういう意味ですか?それらが何であるかは 'errno'の値であり、それらは等しくないので、それらはいつでも*設定することはできません。 –

+0

私はいつもif条件に陥ることを意味します。でも、私はしたくないです。 – lllook

+0

しかし、それは 'errno == EWOULDBLOCK'か' errno == EAGAIN'とはまったく違うものです。 –

答えて

5

はタイムアウトをチェックするための3つのオプションがあります(!私はあなたがやっていると仮定し、あなたが本当にその部分を表示する必要があります)

  1. 使用SO_RCVTIMEO。次にerrnoEWOULDBLOCKまたはEAGAINに設定します。ブロッキングソケットでこのエラーが発生した場合、を認識しています。タイムアウトしていないと、特定のエラーセットが返されませんでした。ノンブロッキングソケットの場合、このメソッドは意味をなさない。

    このオプションのsetsockopt()への引数は、プラットフォームによって異なります。 POSIXプラットフォームでは、引数はstruct timevalへのポインタであり、WindowsではDWORDへのポインタです。また、Windowsではrecv関数が実際にはが、タイムアウト時にWSAETIMEDOUTを返します。

    ソケットがSO_RCVTIMEOを使用してタイムアウトすると、それは不確定な状態にあり、これ以上使用しないでください。それを閉じて再接続します。

  2. SO_KEEPALIVEを使用してください。タイムアウトを設定する標準またはプラットフォームに依存しない方法はありません。デフォルトは2時間です。 recvコールは、errnoETIMEDOUTに設定されていると失敗します。

  3. プロトコルにキープアライブシグナリングを追加します。メソッドのいずれかを使用して


、(LinuxやOSXのような)POSIXプラットフォーム上で、あなたはこの

l = recv(...) 
if (l < 0) 
{ 
    if (errno == EWOULDBLOCK || errno == EAGAIN) 
    { 
     // Timeout, handle it somehow 
    } 

    break; // Exit receiving loop 
} 

のようなものをチェックし、ここで重要な部分は、あなた実際にない限りerrnoをチェックしないことですご理解くださいエラーがあります。 recvが負でない値を返した場合、errnoの値は不定です。

EWOULDBLOCKEAGAINのどちらも設定されていないので、確認する必要があります。

+0

例を表示できますか?私は条件が間違っていると思う – lllook

0

ETIMEDOUTが設定されているかどうかを確認する必要があります。 はman page of recv(3):

からETIMEDOUT 接続は、接続確立時、タイムアウト、またはアクティブな接続上で送信タイムアウトに起因します。

+1

OPは 'recv()'を使用しているため、接続確立時やアクティブ接続時の送信タイムアウトによりタイムアウトが発生することはありません。 –

+0

誰かが "アクティブな接続での送信タイムアウトのため"という意味を教えていただけますか? "recv"を使っている間に "送信"が意味することは何ですか? – Subbu

関連する問題