0

これが私の状況です。私はUDPを使用しており、データを送信しているサーバーがありますが、パケットが失われたためにデータを送信できない可能性もあり、再送信してもらいたいのですが、クライアントはもデータを受け取っていないので、彼に読み直してもらいたい。今のところ、一定時間待機してから再読み取りするクライアントでタイムアウトを使用することにしました。私の問題は、問題を解決するために選択に戻るgotoを追加するだけですか、それとも最初のタイムアウト後に選択が壊れますか? ソケットを非ブロックにする必要がありますか? ネットのどこかで読んだ。基本的に、私の目標は、読み取りが行われない場合、送信者が送信しようとしていることがわかっているため、一定期間後に再試行することです。テストする方法がないため、ロジックが正しいかどうかを知りたいです。

  fd_set set;
  struct timeval timeout;
  int rv;
  char buff[100];
  int len = 100;

  FD_ZERO(&set); /* clear the set */
  FD_SET(sockfd, &set); /* add our file descriptor to the set */

  timeout.tv_sec = 0;
  timeout.tv_usec = 10000;

  retry:
  write(sockfd,"hi",3);//sent to client now waiting for an ack
  rv = select(sockfd + 1, &set, NULL, NULL, &timeout);
  read(sockfd, buff, strlen(buff), 0);
  if(rv == -1)
    perror("select"); /* an error accured */
  else if(rv == 0)
    printf("timeout");
    goto retry;
  else
    read( filedesc, buff, len ); /* there was data to read */
}
4

1 に答える 1

1

select が fd_set を変更して、読み取り後に sockfd が含まれないようにすることを期待します (読み取りの準備ができていなかったため)。したがって、再試行する前にセットを再初期化する必要があることを確認してください。または、タイムアウト後に fd がまだ存在するかどうかを試すこともできますが、select を呼び出す前にすべての FD を再初期化するのが通常の動作だと思います。poll または epoll を使用する場合は、その必要はありません。

それとは別に、コードは問題ないようです。

ブロックインまたは非ブロック IO のどちらを使用するかは、ケースの読み取りには関係ありません。非ブロッキングを使用すると、書き込みが失敗する可能性があるため、ブロッキングを維持する方が簡単です。

于 2013-10-18T19:38:52.713 に答える