質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.84%

  • C

    3333questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • TCP

    149questions

    TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

socket通信におけるselectに関する質問

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 436

BitMaPT

score 17

selectのmanページのバグの項目において以下のような記述があります。

Linux では、 select() がソケットファイルディスクリプターで "読み込みの準備ができた" と報告した場合でも、 この後で read を行うと停止 (block) することがある。このような状況は、 例えば、データが到着したが、検査でチェックサム異常が見つかり廃棄された時 などに起こりえる。他にもファイルディスクリプターが準備できたと間違って 報告される状況が起こるかもしれない。 したがって、停止すべきではないソケットに対しては O_NONBLOCK を使うとより安全であろう。

ここで疑問に思ったのが、このような状況になった時はrecvでデータを受け取ろうとしても何も得られないのは予想できますが、得られるはずだったデータを得るためにはどのようにすればよいのかです。単純にもう一度selectからやり直してデータを正しく受け取るのを待つだけでよいのでしょうか?

(追記)
いくつか不備があったので追記します。

  • プロトコルはTCPです。
  • 勉強のためにselectなどを直接使い、ライブラリは使用しません。
  • 使用言語はCです。
  • 上の質問はO_NONBLOCKを使用したときを想定しています。
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+2

いえ、TCPの場合はTCPの再送制御を思い出してくださいな。
サーバー側からのACK確認応答がないため、クライアントはパケットを再送します。

このバグの説明はselectの待機で疑似覚醒(スプリアスウェイクアップ)が発生し、
ブロッキングソケット(O_NONBLOCKオプションなし)の場合、
readでパケット待機待ちのブロックが発生するという話です。

ネットワークプログラミングを作成する時は、自力でselectやread/write(recv/send)を行わずにライブラリを使用したほうがバグの発生を防げると思います。あとテストが大変です。


<前提知識>
ソケットには入出力の完了を待つ(ブロッキング)、完了を待たない(ノンブロッキング)があります。

種類 O_NONBLOCKオプション
ブロッキングソケット 指定なし
ノンブロッキングソケット 指定あり

質問文のこの部分は

Linux では、 select() がソケットファイルディスクリプターで "読み込みの準備ができた" と報告した場合でも、 この後で read を行うと停止 (block) することがある。

selectでブロッキングソケット(O_NONBLOCK指定なし)の監視を行っている状態です。


O_NONBLOCKオプションを設定しているなら、質問文の問題は発生しません。
1,受信データのロスト→ACK応答が無いので再送される。
2,readでblock→ノンブロッキングソケットなため入出力はブロックしない。
select→FD_ISSETの受信ループに戻せばいいです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/09 19:09

    回答ありがとうございます。いくつか確認したいことがあります。

    >サーバー側からのACK確認応答がないため、クライアントはパケットを再送します。
    これのサーバーとクライアントは逆でしょうか?クライアント側がACKを送らなかったからサーバーがパケットを再走するという話なら理解できます。

    >自力でselectやread/write(recv/send)を行わずにライブラリを使用したほうがバグの発生を防げると思います。
    勉強のためにライブラリを使用していません。質問文にその説明がなかったのは不適切でした。

    スプリアスウェイクアップによってselectから抜けた時、O_NONBLOCKを用いていた場合は、何らかの方法でスプリアスウェイクアップであると判断して再びselectを呼び出して待機する、という風にすればいいのでしょうか?

    キャンセル

  • 2018/01/09 19:29

    1,いえ、サーバーの話ですが、listen したソケットに対してselect で待機です。
    2,O_NONBLOCKならノンブロッキングソケットですが。
    サーバー/クラアント、ブロッキングソケット/ノンブロッキングソケット混在してませんか?

    前提条件を明確にしませんか?
    私の回答はサーバー側でlisten したブロッキングソケットに対してselect で待機後の話です。

    キャンセル

  • 2018/01/09 20:02

    条件が不明瞭でした。申し訳ございません。サーバー側のacceptで得られたノンブロッキングソケットを用いた時の話をしていました。
    質問はノンブロッキングソケットを使用した時はrecvで何も得られず、すぐにselectに戻ればいいのでしょうかという意図の質問でした。
    編集後の解答を拝見させていただきました。非常にわかりやすい解説で、どのようにプログラムをこれから組んでいくかが鮮明になりました。ありがとうございます。
    以後、質問内容の解釈の齟齬が生まれないよう、気を付けていきたいと思います。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.84%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C

    3333questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • TCP

    149questions

    TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。