トップページ⇒tech
1001コメント360KB

ネットワークプログラミング相談室 Port24

■ このスレッドは過去ログ倉庫に格納されています
0001lmtp2009/07/07(火) 00:46:28
主にソケットに関しての質疑応答スレッドです。

Programming UNIX Socket FAQ (日本語訳)
 http://www.kt.rim.or.jp/~ksk/sock-faq/indexj.html
Winsock Programmer's FAQ (日本語訳)
 http://www.kt.rim.or.jp/~ksk/wskfaq-ja/

関連リンクは>>2-10辺り
足りなかったら適当に付け足してね

前スレ
ネットワークプログラミング相談室 Port23
http://pc12.2ch.net/test/read.cgi/tech/1230466044/
関連スレ
ネットワークプログラミング雑談
http://pc12.2ch.net/test/read.cgi/tech/1235800707/
Java ネットワークプログラミング 【教えて!】
http://pc11.2ch.net/test/read.cgi/tech/1086238859/
0166デフォルトの名無しさん2009/07/30(木) 16:43:23
馬鹿に凶器持たせるようなことすんなよ・・・
0167デフォルトの名無しさん2009/07/30(木) 23:04:22
select() を使って recv() すると WSAEWOULDBLOCK って出ないはずですよね?
0168デフォルトの名無しさん2009/07/30(木) 23:15:36
>>167
非同期系ではそういう幻想を持たないほうがいい。
0169デフォルトの名無しさん2009/07/30(木) 23:20:34
>>168
そうなんですか。あるんですか。。
デバッグ中にブロックされていないはずの recv() が WSAEWOULDBLOCK を
返すところを見ちゃった気がするのですが気のせいだと思ってました。 orz
0170デフォルトの名無しさん2009/07/30(木) 23:45:35
届いてたけど拾いにこないから捨てちゃったとか?
通常ありえないよ。
デバッガで止めてたからとか。
0171デフォルトの名無しさん2009/07/31(金) 00:45:32
>>169
戻りを確認するifを入れて実際に起きるかどうか確認すればいい。
0172デフォルトの名無しさん2009/07/31(金) 11:25:21
>>165
「ERROR:ブラウザを立ち上げなおしてみてください。」
て出てきてできなかった。

http://www1.axfc.net/uploader/Sc/so/23023.zip
0173デフォルトの名無しさん2009/07/31(金) 22:26:18
>>170-171
確かにデバッガで止めてはいたのですが。。
色々調べてみるとWin9x系では起きるがNT系では起きないとか
select()はブロックされない事を完全には保証しないとか。

サンプルプログラム等をみるとselect()は非ブロックキングソケットを
使うのが前提となっているみたいですな。
ブロッキングされないのが保証されるのならブロッキングソケットでも
問題ないはずですが。
0174デフォルトの名無しさん2009/07/31(金) 22:32:30
ブロッキングだからこそselect必須。
ブロックされないのが保証できないなら、インターネット動いてねーわ。
0175デフォルトの名無しさん2009/08/01(土) 00:04:37
>>173
ブロッキングの意味を間違えて理解してる気がする。

あと、
>select()はブロックされない事を完全には保証しないとか。
という一文についても、日本語の解釈が誤っているのでは?
これは、ソケットにデータが到着していないにもかかわらず、
selectが戻ることがある(=ブロッキングを保証できない)、
という意味だと思う。言い換えると、selectが戻っても
いざreceiveしてみると受信データ長=0になることも時にはあるから、
その場合はもう一度selectをかけておくれ、を期待しているのではないかな。

最後におせっかいを言うと、何かトラブルが発生したとき、
「....だから、問題ないはず」という思い込みは解決のさまたげになる。
「....だけど、どこかに問題があるはず」という発想でいこうよ。
0176デフォルトの名無しさん2009/08/01(土) 00:20:24
>>175
受信データ長=0はfinがきたってこと。
それでもう一度selectって処理は普通しない。
そうでなければTCP的に言えば受信データ長0ってのは
確認応答しかありえない。これは上位レイヤーに届くことはない。

と言ってみる。
0177デフォルトの名無しさん2009/08/01(土) 00:28:02
平たく言えばアプリケーションレイヤで何かを受信した場合、
長さ1以上はデータ、0は通信の終了を意味する。
TCPがデータストリームの実装だという事を忘れている。
0178デフォルトの名無しさん2009/08/01(土) 00:40:25
>>176
では、
>いざreceiveしてみると受信データ長=0になることも時にはあるから、
の部分は、
>いざreceiveしてみるとエラー(EAGAIN or EWOULDBLOCK)になることも時にはあるから、
に訂正する。
0179デフォルトの名無しさん2009/08/01(土) 12:10:55
「ERROR:ブラウザを立ち上げなおしてみてください。」 って出てきて
2chへの書き込みができない。誰か助けて!

http://www1.axfc.net/uploader/Sc/so/23023.zip
0180デフォルトの名無しさん2009/08/01(土) 13:02:00
http://pc12.2ch.net/test/read.cgi/tech/1247438792/
C/C++の宿題片付けます 129代目
http://pc12.2ch.net/test/read.cgi/tech/1242876647/
いろんな言語で宿題スレ
http://pc12.2ch.net/test/read.cgi/tech/1197620454/
C#,C#の宿題片付けます。
0181デフォルトの名無しさん2009/08/01(土) 13:10:28
Linux だと「select が『読める』といっても read で
ブロックすることあるよ」って書いてあるな。
0182デフォルトの名無しさん2009/08/01(土) 13:25:00
>>180
宿題スレに書けと? 宿題じゃないんだけど。
0183デフォルトの名無しさん2009/08/01(土) 16:22:15
>>181
これか・・・
http://www.linux.or.jp/JM/html/LDP_man-pages/man2/select.2.html
>データが到着したが、検査でチェックサム異常が見つかり廃棄された
>時などに起こりえる。

一体どこで検査してんだ
破棄したなら上に投げるなよw
明らかに違反してるだろ
時など、って他にもあるなら書けよ
省略すんなよ
0184デフォルトの名無しさん2009/08/01(土) 18:40:57
宿題じゃなくても丸ごと依頼するなら宿題と同じだ。
自分でネットの勉強ぐらいしろよ。
0185デフォルトの名無しさん2009/08/01(土) 18:51:30
>>182>>179
http://pc12.2ch.net/test/read.cgi/tech/1224449899/
01861732009/08/01(土) 20:36:54
>>181
それって酷い気がする。
NT系だとブロックしないらしいけど念のためwoodblockは
スルーするように実装しました。
0187デフォルトの名無しさん2009/08/02(日) 05:48:55
>>183,186
Linux TCP/IPドライバの中の人を擁護してみると、
一般論としてselectを前提にしたAPI(ソケット/デバイス/ライブラリなど)の場合、
selectでREAD可能を返したのにread操作でデータ無しとなってしまう事態は、
どうしても避けることができないケースが存在しえることを理解してほしい。
今回のLinux TCP/IPドライバの場合、受信割り込みの延長でのチェックサム計算は
(システム全体の応答性能を劣化させるから)避けたかったのだろうと推測する。

だから最近のAPIでは(特にGUI向けAPIでは)、APIの内部でevent loop & selectを実行し
本当にデータが到着した場合にだけ(事前にアプリケーションが登録した)
call back関数を呼ぶという方式が増えているのだと思う。
この方式であれば今回のselectの問題だけでなく、このスレでたびたび話題となっている
受信メッセージの組み立て処理もAPI側で吸収できる(アプリケーションから隠蔽できる)
利点がある。

0188デフォルトの名無しさん2009/08/02(日) 08:35:44
>>187
> 今回のLinux TCP/IPドライバの場合、受信割り込みの延長でのチェックサム計算は
> (システム全体の応答性能を劣化させるから)避けたかったのだろうと推測する。

割り込み処理は, 読み込んだ物理層のフレームをソケットバッファにつないで
ソケットバッファ持ってるプロセス(スレッド)を起こすだけ.

IPヘッダやさらに上位の層のチェックサムはプロセスコンテキストで計算して
る

到着したセグメントを捨てた後, 再度新規セグメントの入力待ちに移行する方
法を選択しなかっただけ.

おそらく, 初期の腐りきったスタックの挙動と互換性を取る為だとおもわれる.
0189デフォルトの名無しさん2009/08/02(日) 09:02:37
腐りきったってw
TCP/IPのタイムアウトの設定なんかかなり古いもんを引きずっている気がする。
connect()なんてタイムアウトまで待ちきれなくて自分で切ってるし
TIME_WAITなんかも長く居座り過ぎだし。
今のギガビットのネットワークにはそぐわないな。

0190デフォルトの名無しさん2009/08/02(日) 09:20:05
>>189
> TIME_WAITなんかも長く居座り過ぎだし。
RFC で 2MSL と決まってる
01911872009/08/02(日) 09:28:17
>>188
詳しい解説ありがとう。TCP/IPドライバの実装に詳しそうだから教えてほしいのだけど、

>割り込み処理は, 読み込んだ物理層のフレームをソケットバッファにつないで
>ソケットバッファ持ってるプロセス(スレッド)を起こすだけ.
とありますが、起こすのはシステムプロセス(システムスレッド)でいいのでしょうか?
もしアプリケーションプロセスだと、そのプロセスが監視(select or recv)していない時は
フレーム受信キューに溜まりっぱなしになってしまう訳だから。

ただ、そうだとすれば、チェックサム計算はシステムプロセスで実行して
エラーであれば破棄し、正常であれば(上位の)ソケット受信キューへつないで
アプリケーションプロセスを起こすように実装していれば、
(チェックサム計算エラーに限定すると)今回のselect問題は発生しなかったように思えます。
その辺が自分にはよく分からないのですよ。
0192デフォルトの名無しさん2009/08/02(日) 10:07:53
>>191
> とありますが、起こすのはシステムプロセス(システムスレッド)でいいのでしょうか?
そだよ.

> フレーム受信キューに溜まりっぱなしになってしまう訳だから。
どっちにしても, 受け取る奴がいないとたまりっぱなし
window size = 0 で ack 返して送信側がそれ以上送らないように制御する
UDP だと黙って捨てる

> エラーであれば破棄し、正常であれば(上位の)ソケット受信キューへつないで
> アプリケーションプロセスを起こすように実装していれば、

BSD 系の実装だとそうなってるし, Linux も 2.0 から 2.2 へ移行するときの
大幅にスタック書き換えたタイミングで, そうゆう実装をする選択枝も可能
だったはず.
ソース眺めても, そんなに大変な変更じゃないし………

結局は, 過去との互換性を取ったって事ではあるまいか?
0193デフォルトの名無しさん2009/08/02(日) 10:14:35
玉味噌な人だな〜
0194187,1912009/08/02(日) 10:21:39
>>192
過去との互換性ですか。
もしTCP/IPスタックの実装を参考にしようと思ったら、
(Linuxではなく)BSD系のコードを追ったほうが良さげですね。

どちらにしてもスレから脱線した質問ですので、これで終わりにします。
レスありがとうございました。
0195デフォルトの名無しさん2009/08/02(日) 11:54:18
いや、こういう挙動の話はためになる
もっと続けて欲しい
0196デフォルトの名無しさん2009/08/02(日) 12:26:02
ネットーワークプログラミングってアンドキュメントなお決まり事があったり、
ネットで拾えるサンプルプログラムがDQNな実装(特に.Net系)だったりするので
挙動が分かってないと苦労しまするよ。
0197デフォルトの名無しさん2009/08/02(日) 12:27:58
>>187
> 受信割り込みの延長でのチェックサム計算は(システ
> ム全体の応答性能を劣化させるから)避けたかったの
> だろう

昔組み込み向けネットワークドライバを Linux でクロ
ス開発してて、テストとして Linux のパケットをルー
プバックデバイス経由で RAW ソケットで読んでもチェッ
クサムが合わなくてさぁ…。

FreeBSD でやったら一発で通って「なんじゃそら」って
なもんでしたよ。
0198デフォルトの名無しさん2009/08/02(日) 12:32:20
本採用な鯖でlinuxが使われない理由がなんとなく判った
0199デフォルトの名無しさん2009/08/02(日) 12:35:21
>>198
そうなん?
Linux鯖って結構稼動している気がするが。
0200デフォルトの名無しさん2009/08/02(日) 15:15:26
いまどき、IPはもちろん、TCPチェックサムまでは、送信受信ともハードウェアの仕事でしょ。
パケット生成時にチェックサム作るなんてことしない。
その辺考慮してないと197みたいなことになる。
0201デフォルトの名無しさん2009/08/02(日) 15:57:39
基本的な質問だと思うけど、うまく見つけられなかったのでおせーてください。

自分のルータのグローバルIPアドレスを外部鯖にHTTP接続して取得したいのだけど、
【IPのみ】をページ表示してくれる有名な鯖とかってある?

本当はホスト名を一発表示してくれるとこがいいけど、
まーAPIでなんとかなるんでとりあずIPで!
02022012009/08/02(日) 15:59:44
上の文章だとわかりづらかったので補足。

IPのみというのは、IPアドレス以外の無駄な情報が無いってこと。
正規表現とかHTMLパーサーとか使うのが面倒なので・・・。
0203デフォルトの名無しさん2009/08/02(日) 16:02:16
ルータに聞けばいいじゃない
02042012009/08/02(日) 16:03:50
>>203
汎用的な方法がしりたいんでつ
いろいろな場所で使いたいので、ルータ固有となるとちょっと・・
SNMPも一般向けのルータにはあまりないらしいので。
0205デフォルトの名無しさん2009/08/02(日) 16:25:49
>>204
汎用的な方法は、自分のルータのグローバルIPアドレスを
Dynamic DNSに登録して、その名前でIPアドレスを検索すること。
登録するドメインは自分で取得してもいいし、借りてもいい。

おそらく自宅鯖を外部からアクセスしたいんだとエスパーするけど、
汎用的な方法はこれしかない。

DNSへの登録が嫌で、なおかつ汎用的でなくても良ければ、
自分で安いレンタル鯖を借り、要求元のIPだけを返すCGIを置けばいい。

いずれにしても板違いの質問だよ。
自宅サーバ板/通信技術板/ネットサービス板へドーゾ。
0206デフォルトの名無しさん2009/08/02(日) 16:27:38
>>200
へぇ〜、そんなハードもあるんだ。。
一般のパソコンにも実装されてるの?
0207デフォルトの名無しさん2009/08/02(日) 16:35:00
>>201
そういうサーバを立てればいいだけじゃね?
0208デフォルトの名無しさん2009/08/02(日) 16:38:38
>>200
> いまどき、IPはもちろん、TCPチェックサムまでは、送信受信ともハードウェアの仕事でしょ。
> パケット生成時にチェックサム作るなんてことしない。

NAT とかどうすんのさ。仮想レイヤは? 一々ハードウェ
アレイヤまで落すのか? そもそも NIC 持ってないマシ
ンでの SLIP とかどうすんの?
0209デフォルトの名無しさん2009/08/02(日) 16:42:49
DDNSは運用面で問題有るから、うざいのが本音だな。
基本reject_hostに入れてる。

犬のTCP/IPスタック周りの挙動は怪しいよな。学習用のminix由来じゃしょうがないが。
0210デフォルトの名無しさん2009/08/02(日) 16:48:04
>>209
> 学習用のminix由来

Minix なめんな(w
http://www.minix3.org/
0211デフォルトの名無しさん2009/08/02(日) 16:50:58
DDNSをreject_hostに入れるって何の話よ
02122012009/08/02(日) 16:52:57
>>205>>207
板違いなのに答えてくれてサンクス
自分がだけが使うわけではないから、DynamicDNS登録もcgiもパスかな。
素直に診断君とか、適当な鯖にUDP送って取得することにする
どもでしたー
0213デフォルトの名無しさん2009/08/02(日) 16:53:14
>>206
おそらく以下の記事にある「TCPチェックサムオフロード」の事を
>>200は言っているのだと思う。

FreeBSD 10ギガビットネットワーク高速通信の秘密(2008/10/29)
 [3] ハードウェアオフロードによる処理の高速化
http://journal.mycom.co.jp/articles/2008/10/29/bsdcon5/002.html

ただしサポートしているのは一部のサーバ向けハイエンドNICだけだったはず(?)だし、
ましてや>>197は「組み込み向けネットワークドライバ」と明記しているから、
>>200の言う「いまどき」が何を(or いつの時代)を指しているのかよくワカランwww
0214デフォルトの名無しさん2009/08/02(日) 16:54:48
正常切断でこんなロジックを見かけるけど、これってありなの?
shutdown(soc, SHUT_RDWR);
close(soc);
0215デフォルトの名無しさん2009/08/02(日) 17:37:52
>>213
何年前から来たんだよ。FEの時代は高級品だけだったけど、GbEならオンボだつて蟹だってついてる。>TOE
Windowsのハードウェアのプロパティにチェックサムオフロードの設定あるだろ。
オフロードが効いてるとWiresharkでチェックサムエラーになるから判る。
Linuxは、ドライバ設計が古くてTOE使えない時期が長かったけど、流石に今は対応してたはず。
0216デフォルトの名無しさん2009/08/02(日) 17:44:54
>>214
通信シーケンスに自信がないなら入れておくという程度。
sdの状態的にSHUT_RDWRを指定した時FINハンドシェークが起こるが、
closeをいきなり呼んでも暗黙的にこの処理は行なわれる。
半二重通信でもしない限り明示的なshutdownは必要ない。
ただし、能動通信側が送りっぱなしで突然閉じるようなことをすると、
shutdown無しの場合受動通信側のパケットを無駄に待ってしまったりと
sdが完全に無効になるまで時間が掛かる場合がある。
0217デフォルトの名無しさん2009/08/02(日) 18:03:18
>>216
shutdown(SHUT_WR)
recv() でゼロかエラーが帰ってくるまで待つ。
(どちらも帰って来ない場合もあるのでタイムアウト処理を入れる)
close()

こんな面倒くさい(お行儀の良い)処理をしなくて一方的に切断しても特に
問題ないって事ですか?
0218デフォルトの名無しさん2009/08/02(日) 18:26:47
>>215
>Linuxは、ドライバ設計が古くてTOE使えない時期が長かったけど、流石に今は対応してたはず。
いやデスクトップはいいんだけど、>>197の言う「組み込み向けLinuxボード」でも対応してますか?
>>206の質問にある、(チェックサムオフロードをサポートした)ハード(ボード)にも答えて下さいませ。
あなたは>>200のレスで、>>197に対して「いまどき」と発言しているんですが........。
一般的な事実(独り言)としては正しいのかもしれないけど、質問に対する返答になってない気がします。
0219デフォルトの名無しさん2009/08/02(日) 18:52:09
犬廚はウィンドウズのドライバの詳細項目なんてチェックしないと思うけどな。
TOEってちゃんと動くか? 動かない条件のほうが多いと思うよ。
0220デフォルトの名無しさん2009/08/02(日) 19:29:20
>>219
>TOEってちゃんと動くか? 動かない条件のほうが多いと思うよ。

いや、>>215の住む世界だと、Linux/WindowsともGbEでさえあれば、
TOEが動くのが今時は当然な事らしい....。
0221デフォルトの名無しさん2009/08/02(日) 20:00:40
>>218
話をややこしくして済まないんだが、「クロス開発」で
あって別に Linux 向けの組み込みじゃなかったのよ。
ターゲットは OS から俺一人で書いた奴(RISC CPU で
メモリがバンク切り替えな環境)。

でもって開発環境だった Linux をネットワークドライ
バテストの対向ルーチンにしようとしてて、たとえば
UDP パケットを Linux 側で作ってループバックデバイ
ス通して RAW ソケットで読んで自前のドライバのテス
トケースに突っ込んで…ってなことをやってたわけ。

別にハードウェアで計算するならするでいいけどさ、そ
れなら仮想的なループバックデバイスを使う場合はそこ
で計算すべきじゃないかと思うんだ(計算しない理由は
パフォーマンスを稼ぎたいというのが正解で、コンパイ
ルオプションで計算が有効になるようになってたところ
までは調べた)。

因みにちょっと前にあった「NAT 通した時にチェックサ
ムおかしいんだけど…」なんていうバグはこの辺に起因
してる気がする。くわばらくわばら(w
0222デフォルトの名無しさん2009/08/02(日) 20:20:07
>>217
だからぁ、「一般的には問題ない。でも、ある特別なケースでは
問題となるかもしれない」と>>216はレスしている。
その可能性のあるケース(の一部)も>>216でレスされている。
それが>>217に当てはまるかどうかは、>>217が想定してる状況を
明記してくれないと、エスパーでもない限り誰にも返答できないよ。

横レス失礼
0223デフォルトの名無しさん2009/08/02(日) 20:59:17
>>222
>>216 は、
shutdown(SHUT_RDWR)
close()
と
close() #暗黙的にshutdown処理されるので
は同じだと言っている。

であればshutdown()は意味のないことに成る。

だったら、>>217 の処理はしなくて close() でいきなり
ソケットを閉じても問題ないってこと?

TIME_WAITで処理されるのでどんな切り方をしょようと
結局は皆同じってことでよいのかな??
0224デフォルトの名無しさん2009/08/02(日) 21:23:38
逆に言えばshutdown入れとけばどんな切り方してもいいから入れとけ。
0225デフォルトの名無しさん2009/08/02(日) 21:33:51
鯖が迷惑するとか考えないのかな。
IPBANされるぞw
0226デフォルトの名無しさん2009/08/02(日) 21:42:11
>>224
(゚◇゚)ゞラジャ -
でも、shutdownしたら鯖の電源が落ちました〜
0227デフォルトの名無しさん2009/08/02(日) 21:53:59
鯖が先に切るのか、クライアント側が先に切るのか、
実際はプロトコルによって変わるとしか言えない。
APIの呼び出し手順みたいな単純な話には置き換えられない。
0228デフォルトの名無しさん2009/08/02(日) 22:01:16
組み込みでもチェックサム生成ぐらいの機能なら
ハードウェアに用意してある場合が多い。
もっともエラータで使えなかったりするが。>microchipのやつ
02292222009/08/02(日) 22:17:58
>>223
だから、「一般的」には

>だったら、>>217 の処理はしなくて close() でいきなり
>ソケットを閉じても問題ないってこと?

で問題ないと(>>216の先頭に)書いてあります。

>TIME_WAITで処理されるのでどんな切り方をしょようと
>結局は皆同じってことでよいのかな??

これも、「一般的」には同じと考えてかまいません。

でもね、数百、数千台のクライアントの相手をしなければならない
サーバ環境を想定してみてください。大量に残ってしまった
(カーネル空間内の)TIME_WAIT待ち状態が、システム性能に
深刻な悪影響を与えかねないという事は分かってもらえますか?

もしもそのようなシビアな状況を想定しているのであれば、
(>>216にある「送りっぱなしで突然閉じる」ようなことをせずに)
きちんと手順をふんでTCPコネクションを解法するよう実装すべきです。
でも、>>217,223の想定している状況がどれほどシビアなのかは
本人にしか知り得ないから、誰にも返答できないと>>222でレスしました。
0230デフォルトの名無しさん2009/08/02(日) 22:33:24
>>229
>サーバ環境を想定してみてください。大量に残ってしまった
>(カーネル空間内の)TIME_WAIT待ち状態が、システム性能に
>深刻な悪影響を与えかねないという事は分かってもらえますか?

どんな切り方をしようが先にshutdown()した方にTIME_WAIT状態の
セッションが2MSLは残るんじゃないの?
02312222009/08/02(日) 22:51:27
>>230
失礼、>>229内にあるTIME_WAITは誤りで、FIN_WAITに訂正します。
(>>216にも、きちんと「FINハンドシェークが...」と書いてありました)
0232デフォルトの名無しさん2009/08/02(日) 23:16:01
>>231
FIN_WAITって鯖側のソケットをclose()しても残ったままになるの?
02332222009/08/02(日) 23:19:47
>>232
TCPの状態遷移図を(RFCなどで)確認してみてください。
0234デフォルトの名無しさん2009/08/02(日) 23:35:32
えーと、TCP/IP って双方向通信だって事忘れてない?

世の中には一方通行通信で良い場合もあるし、一方通行
で構わないタイミング(たとえば、片方は言いたいこと
を全部言い終わったとか)もある。shutdown() で片方
閉じるってのは元々そういう用途だよ。
0235デフォルトの名無しさん2009/08/02(日) 23:39:05
>>233
RFC見ましたがソケット関数とtcp状態遷移の関係がわからない。。
首吊って人生やりなおしてきます。orz
0236デフォルトの名無しさん2009/08/03(月) 00:15:25
RAWソケットで実際につくってみたらいい
0237デフォルトの名無しさん2009/08/03(月) 00:25:55
>>235
よく見掛ける状態遷移図は参考程度にしといた方がいいっ
てスティーブンスも言ってたんだけど。

http://pfsense.org/~cmb/diagrams/tcpStateDiagram1.gif

たとえば↑で斜体になってるのがアプリが呼び出すメソッ
ドと思えばいい。んでもって矢印が状態遷移だけど、
A/B というのは「A が発生したら B を実施して遷移す
る」の意味。「Close/FIN」はアプリが close() したら
FIN を送出して状態遷移。

そして TCP/IP は双方が established 状態になったら
サーバ/クライアントなんていう区別は無くなるんだよ
(そもそも、双方同時に Active open してもコネクショ
ンが張れるように設計されてる)。

ESTABLISHED から下に遷移している左側がアプリによる
close() の遷移で、右側がその応答である FIN を受け
取ったときの遷移。

双方同時に close() したらどうなるかとか考えてみる
といいよ。
0238デフォルトの名無しさん2009/08/03(月) 00:30:39
おっと、書き忘れてた。

CLOSE_WAIT ってのは「FIN は来たからアプリの
close() 待ちだな」っていう状態で、この時まだ送信で
きる状態。

FIN_WAIT ってのは「アプリは close() したから FIN
待ちだな」っていう状態で、この時まだ受信出来る状態。
02392222009/08/03(月) 00:43:00
>>235
文書 "RFC 739" 内の図 "Figure 6. TCP Connection State Diagram" は
参照されていると思います。(もし見ていなければ開いてください)

この図の中央に状態 [ESTAB(コネクション確立中)] があります。
この状態でソケットから事象 "CLOSE" を受け付けると、
(TCPスタックは)IPスタック(=クライアント)へ事象 "snd FIN(FINパケットの送信)" を要求し、
(図の左下側にある)状態 [FIN WAIT-1(コネクション解放待ち(1)] へ遷移します。

ここでソケットからの事象 "CLOSE" は、実際にはshutdownかもしれませんし、
(>>216で「closeをいきなり呼んでも暗黙的にこの処理は行なわれる」とあるように)
いきなりのcloseかもしれないし、あるいは(プロセスのexitに伴う)カーネル内部の
close操作かもしれません。そこは実装に依存するのでRFCでは抽象的に記述されています。

で、状態 [FIN WAIT-1(コネクション解放待ち(1)] においては、IPスタック(=クライアント)から
事象 "rcv ACK of FIN(FINに対するACKパケットを受信)"、
あるいは事象 "rcv FIN(FINパケット受信)" を受け付けない限り、
(永遠に)次の状態へは進めない(遷移できない)ことが確認できるのではないかと思います。
これが「(質問>>232にある)鯖側のソケットをclose()しても残ったまま」になる状況(の一例)です。

眠いんで、今晩はこれで落ちます。
0240デフォルトの名無しさん2009/08/03(月) 00:43:16
>>237-238
アリガトン
でも、その図の何処にもshutdown()が出ていない (´;ω;`)
あの世へ逝ってスティーブンス先生に教えてもらいます。 orz
0241デフォルトの名無しさん2009/08/03(月) 00:51:21
>>239
>(永遠に)次の状態へは進めない(遷移できない)ことが確認できるのではないかと思います

タイムアウトは実装しているだろうから永遠にって事はないでしょ。
10分くらい放置プレイされるらしいけど。
0242デフォルトの名無しさん2009/08/03(月) 01:02:45
>>237
その図でもshutdownの各パラメータとの対応とrecv()がゼロを返す
タイミングとかはわからんな。ある程度は想像付くけどね。

でも、そんな遷移図わからなくてもTCP/IPプログラムの作れて
しまうソッケットって素敵。
0243デフォルトの名無しさん2009/08/03(月) 01:23:59
TCP/IP は双方向だから、こっち→あっちとあっち→こっ
ちの二つのデータの流れがあって、そのどちらも

「SYN, データ列、FIN」

の順序になってる。SYN の前や FIN の後にデータは存
在しない。

SHUT_WR は「もう書くことありません」だから、FIN の
送出だよ(で、FIN_WAIT)。

SHUT_RD は「もう読みたくありません」だけど、あっち
には関係無い話でせいぜいこっち側が受信バッファを解
放する位の事しか出来ない(もちろん、アプリ側にもデー
タは来なくなる)。

TCP だとこんな感じだけど、別プロトコルだとまた違っ
た動作が割り振られてる場合もあるよ。
0244デフォルトの名無しさん2009/08/03(月) 01:35:26
>>241
> タイムアウトは実装しているだろうから永遠にって事はないでしょ。
> 10分くらい放置プレイされるらしいけど。

現実的な問題からそういう実装はあるかもしれないけど、
TCP/IP の規格にそんな話は出てこないよ。

TCP/IP はあくまで信頼性のあるコネクションを提供す
るのが目的だから、たとえば ESTABLISHED 状態でたま
たま双方が最後に送出したデータの ACK を受け取った
まま三日間無通信だったとしても「突然切っていい」な
んて話はないよ(突然切った瞬間にあっちが何か喋るか
もしれない)。
0245デフォルトの名無しさん2009/08/03(月) 01:57:55
TCPの上の層がどうこうって話?
0246デフォルトの名無しさん2009/08/03(月) 07:05:39
>>228
>>208
0247デフォルトの名無しさん2009/08/03(月) 07:07:17
>>244
ESTABLISHED で勝手にタイムアウト切断するのは鬼畜だけど
FIN_WAITでのタイムアウトは良いんじゃね?
どうせ一時的な状態だし。
0248デフォルトの名無しさん2009/08/03(月) 08:16:04
>>247
まず、SHUT_WR の状態では切断出来ないよね。向うから
のデータはまだ到着する可能性があるし、アプリだって
read() するかもしれない。

次に SHUT_RDWR の場合だけど、これも切断できない。

たとえば FIN_WAIT の変わりに TIME_WAIT 状態に入っ
たとすると、向うからのデータは破棄されるから向うは
ずっと再送処理を行う事になる。

FIN_WAIT の変わりに CLOSED 状態に入ったとすると、
向うからのデータに対して RST が送出されるからコネ
クションが切断されてしまう(正常系と動きが異なって
しまう)。それに本来入るべき TIME_WAIT に入らない
というのは、TIME_WAIT によって慎重に取り除かれてい
た「シーケンス番号重複問題」が顔を出すことにもなる
よ。

ひょっとしたらもう少し新しい RFC では話が違うのか
もしれないけど、俺が実装した頃の話の理解ではこんな
感じ。
0249デフォルトの名無しさん2009/08/03(月) 08:38:50
ああ、それから FIN_WAIT_1 に入ったって事は FIN を
送ったんだから、その FIN に対する ACK が来るまで
FIN を再送するんだよ。でないと向うに「全部受け取っ
たよ」っていう通知が届いた事が確認出来ないから。

そして(またもや FIN が到着せずに)FIN_WAIT_2 に入っ
たって事は向うがこっちからの ACK を待ってる可能性
があるから、やっぱり向うからの最終データに対する
ACK を再送することになるよね。
0250デフォルトの名無しさん2009/08/03(月) 08:56:14
>>249
> でないと向うに「全部受け取ったよ」っていう通知が
> 届いた事が確認出来ない

あー、これ逆だ。「全部送り終わったよ」の通知を向う
が受けた事の確認だね。
0251デフォルトの名無しさん2009/08/03(月) 10:27:36
裏にDBが絡んでたりとかして、大量のデータを用意するのに時間がかかる鯖が居て、そいつにデータ用意させるリクエストしといて、勝手にSHUT_WRで斬りまくるのは、礼儀に反しそうだwww
まあhost_denyされても文句は言えないな。
0252デフォルトの名無しさん2009/08/03(月) 10:31:54
SHUT_WR は FIN が届くからそれでクエリキャンセルす
れば無問題。
0253デフォルトの名無しさん2009/08/03(月) 10:33:36
無問題じゃなくて正しい動作か。クエリ送信し終わって
送信端 close() 状態だね。
0254デフォルトの名無しさん2009/08/03(月) 17:14:31
acceptってどういう処理になるの?
シーケンス番号で区別?
0255デフォルトの名無しさん2009/08/03(月) 18:24:04
あ、相手先のIPとポート番号で区別できるね。
むう・・
0256デフォルトの名無しさん2009/08/03(月) 19:12:48
シーケンス番号って32bitしかないけど衝突とかしないのかな
接続ごとにずらすから、しても問題ないのかな
0257デフォルトの名無しさん2009/08/03(月) 19:14:58
うあ、ハッシュ値で管理とか書いてあるな
頭いいな
0258デフォルトの名無しさん2009/08/03(月) 22:43:36
>>253
SHUT_WRしたらrecv()でのゼロを待つんじゃないのか?
そのrecv()のデータは闇に葬られるが。
0259デフォルトの名無しさん2009/08/03(月) 23:01:59
簡易telnet鯖を実装したのですが、クライアントから来る
IAC+2バイトと0(nop)は応答する気がなかったら
無視しちゃっても問題ないですよね?
一応teratermから使えてるみたいなのでいいや。
RFCのtelnetオプション追うの疲れた。
0260デフォルトの名無しさん2009/08/03(月) 23:14:36
>>254
>>255
巷ではよくセッションの区別は

「ローカルアドレス+ローカルポート+リモートアドレス+リモートポート」

だと言われてますが、スティーブンス本をよ〜く読むと
これに加えて「ローカル NIC」っていうのが付きます。

たとえば NIC が二枚挿さってるモバイル PC で、PPP
で割り当ててもらったローカルアドレスが(運悪く)両
方とも同じだった、といった状態が考えられるからです。
0261デフォルトの名無しさん2009/08/03(月) 23:20:39
>>258
手前側で SHUT_WR すると向こう側に FIN が送られます
が、向うからこちらへのデータ送信に影響は無いですよ。
TCP より上のレイヤで「FIN が来たらコネクションクロー
ズ」という約束ごとでも無い限りは。
0262デフォルトの名無しさん2009/08/04(火) 08:05:17
reuseしとけ。
0263デフォルトの名無しさん2009/08/04(火) 17:16:31
AI_ADDRCONFIG フラグってなんのために存在すんの?
これ要らない子じゃね?
0264デフォルトの名無しさん2009/08/04(火) 21:26:39
要る。V4のネームサーバもAAAAレコードを持っている。逆も。
0265デフォルトの名無しさん2009/08/05(水) 21:36:26
IPv6とか邪魔だよな。
■ このスレッドは過去ログ倉庫に格納されています