2012-10-07 2 views
7

5秒ごとにクライアントにデータを送信するサーバーがあります。サーバーがデータを送信してから印刷するまで、クライアントがread()でブロックするようにします。私はread()がデフォルトでブロックされていることを知っています。私の問題は、クライアントがread()をブロックしていないことです。これは非常に奇妙で、これは通常の問題ではないようです。ソケットプログラミングでread()がブロックされていません

私のコードでは、無限ループで「何も戻ってこなかった」と表示されます。私はLinuxマシンで、cでプログラミングしています。私のコードスニペットは以下の通りです。ご意見をお聞かせください。

while(1) 
{ 
    n = read(sockfd, recvline, MAXLINE); 
    if (n > 0) 
    { 
     recvline[n] = 0;  
     if (fputs(recvline, stdout) == EOF) 
      printf("fputs error"); 
    } 
    else if(n == 0) 
     printf("Nothing came back"); 
    else if (n < 0) 
     printf("read error"); 
} 
return; 
+3

接続が開いていることを確認しましたか(つまり、 'sockfd'が有効です)? –

+16

'read()'の戻り値0は、もう一方の端(サーバー)がソケットを閉じたことを意味します。 –

+0

@Edヒール:はい、有効です。私はその点検をしています。 – Mathew

答えて

8

いくつかの原因と、いくつかの例外が別の場所で可能ですがあるかもしれません:

sockfd=socket(AF_INET,SOCK_STREAM,0); 
if (sockfd==-1) { 
    perror("Create socket"); 
} 
  • あなたとも明示的に前のモードを遮断可能:作成

    1. チェックソケットそれを使用してください:

      か、以下のようにsetsockoptを使用することができます。

      struct timeval t;  
      t.tv_sec = 0; 
      tv_usec = 0; 
      setsockopt(
           sockfd,  // Socket descriptor 
           SOL_SOCKET, // To manipulate options at the sockets API level 
           SO_RCVTIMEO,// Specify the receiving or sending timeouts 
           const void *(&t), // option values 
           sizeof(t) 
      ); 
      
    2. チェック読む関数コール(バグの理由)

      n = read(sockfd, recvline, MAXLINE); 
      if(n < 0){ 
          perror("Read Error:"); 
      } 
      
    3. またチェックサーバコードを:!

      1. May your server send some blank(non-printable, null, enter) charter(s). And your are unaware of this. Bug you server code too.

      2. Or your server terminated before your client can read.

    4. もう1つ興味深いもの、理解しよう:

      When you call N write() at server its not necessary there should be N read() call at other side.

  • +1

    丁寧な返事をくれてありがとう。私はサーバーを固定してバグを試み、それが何か厄介なものを送っているかどうかを見てみましょう。 – Mathew

    +0

    ブロッキングモードがデフォルトです。明示的に設定する必要はありません。 (0)とsizeof(sockfd)の引数を持つsetsockopt()を呼び出す(2)のコードは完全なナンセンスであり、コンパイルされません。 Downvote。 – EJP

    +0

    @EJP:私はデフォルトモードがブロックしていることを知っています。ブロッキングモードを明示的に設定する(またはブロッキングモードにリセットする)方法を説明したかっただけです。コンパイルエラー:私はsetsock()オプションのコードと私の要求をあなたに訂正しました。確認してください。まだ間違っていれば、正しいヘルプを得ることができます。EJP!ありがとう! –

    1

    MAXLINEの価値とは?

    値が0の場合は0も返します。 そうでなければ、Grijesh Chauhanが言及しているように、それをブロックするようにexplcitlyに設定してください。

    また、ブロックと非ブロックを指定できるrecv()の使用を検討することもできます。 MSG_WAITALLオプションがあり、すべてのバイトが到着するまでブロックされます。 EOF(つまり、書き込みを明示的に停止され、それはclose()を介して、またはshutdown()を介しても)だから、recv()リターン0を持つことにより、受信側に伝達されます。コメントとしてグレッグHewgillはすでに書いた何

    n = recv(sockfd, recvline, MAXLINE, MSG_WAITALL); 
    
    +0

    良いアイデア!!私はrecv()を試してみてください。それはトリックを行うことができます。 – Mathew

    3

    0を取得した場合は、データが存在しないことがわかり、読み取りループを終了することができます。

    ノンブロッキングが有効で、データがない場合、-1となり、errnoEAGAINまたはEWOULDBLOCKに設定されます。

    +0

    私はこれが問題だとは思わない。サーバーは無限ループにあり、5秒ごとにクライアントにデータを送信し続けます。 bydesignというサーバーは、まったくシャットダウンされません。 – Mathew

    +0

    サーバではありませんが、サーバの "クライアントソケット"はおそらく... – glglgl