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

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

新規登録して質問してみよう
ただいま回答率
85.50%
C

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

TCP

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

Q&A

解決済

1回答

7419閲覧

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

BitMaPT

総合スコア25

C

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

TCP

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

0グッド

1クリップ

投稿2018/01/08 03:16

編集2018/01/09 10:28

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

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

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

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

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

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

いえ、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 05:49

編集2018/01/09 10:47
umyu

総合スコア5846

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

BitMaPT

2018/01/09 10:09

回答ありがとうございます。いくつか確認したいことがあります。 >サーバー側からのACK確認応答がないため、クライアントはパケットを再送します。 これのサーバーとクライアントは逆でしょうか?クライアント側がACKを送らなかったからサーバーがパケットを再走するという話なら理解できます。 >自力でselectやread/write(recv/send)を行わずにライブラリを使用したほうがバグの発生を防げると思います。 勉強のためにライブラリを使用していません。質問文にその説明がなかったのは不適切でした。 スプリアスウェイクアップによってselectから抜けた時、O_NONBLOCKを用いていた場合は、何らかの方法でスプリアスウェイクアップであると判断して再びselectを呼び出して待機する、という風にすればいいのでしょうか?
umyu

2018/01/09 10:29

1,いえ、サーバーの話ですが、listen したソケットに対してselect で待機です。 2,O_NONBLOCKならノンブロッキングソケットですが。 サーバー/クラアント、ブロッキングソケット/ノンブロッキングソケット混在してませんか? 前提条件を明確にしませんか? 私の回答はサーバー側でlisten したブロッキングソケットに対してselect で待機後の話です。
BitMaPT

2018/01/09 11:02

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問