ネットワークプログラミング相談室 Port24
■ このスレッドは過去ログ倉庫に格納されています
0001lmtp
2009/07/07(火) 00:46:28Programming 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/
0784デフォルトの名無しさん
2009/09/13(日) 18:45:45thx!
0785デフォルトの名無しさん
2009/09/13(日) 18:50:101万個くらいつくれるの?
0786デフォルトの名無しさん
2009/09/13(日) 19:27:46他にも制限あるだろうけどね。
0787764
2009/09/13(日) 19:28:48>でもこのアプリはマルチスレッド&非ブロッキングなんですよ。
>>764に挙げたのはselectによるタイマ監視を使用しない、一般的なケースですね。
もし>>750のようにタイマ監視が前提であれば、receiveによるプロセスのブロックは
selectによる監視の妨げになりますから、非ブロッキングなreceiveを使います。
ソケットは1個でも、そのデータ受信イベントとタイムアウト発生イベントを
同時に待ち受けるわけですから、selectの利用は自然な発想だと思います。
あと>>750で気になったのは、acceptをSleepとのループで待っているとの記述です。
acceptも(receiveと同じように)TCPコネクション確立通知イベント発生をタイムアウト付きで
selectを用いて監視できます。Sleepというのが何なのか分かりませんが(おそらくは独自の
マクロかライブラリ関数?)、C標準ライブラリのsleep関数に相当ものであると仮定すれば、
sleepによる待ち時間は無駄ですから、TCPコネクション確立通知に対する応答時間を
遅延させるだけの意味しか持たないように思えます。だから一般的にはタイムアウト付きの
selectでacceptをループさせます。謎のSleepについて、調査する必要があるかもしれません。
(長いので続く)
0788764
2009/09/13(日) 19:34:47>しかし本当の意味?での非ブロッキングはすごく複雑そうですね・・・
非ブロッキング処理を一般的に書くと>>764のようになって難解に見えますが、
その実装方法は「イベント駆動プログラミング」です。GUIアプリ開発では一般的ですよね。
普通の対話型Cプログラムだとscanf/printfのループで処理しますが、イベント駆動なGUIだと、
まずイベント待ちループに入り、マウスクリック/キー押下イベントが発生すると、事前に
登録しておいたアクションが実行され、そのアクションの中でウィジェットを操作します。
ネットワークプログラムにおけるイベント駆動プログラミングも同様に、イベント待ちループ内の
selectでTCPコネクション確立通知/データ受信(複数)/タイムアウトといったイベントの発生を
同時に待ち受け、イベントが発生すると対応するアクションを実行し、そのアクションの中で
独自プロトコルを実装した有限状態機械(Finite State Machine)へ発生イベントを送ります。
何度か開発経験を重ね、慣れてくるとイベント駆動処理を独自のライブラリ関数として
設計できるようになると思います。またGUIアプリ開発でも考え方は同じですから、
その本質を理解できれば、Webブラウザやメーラのようなネットワーク対応GUIアプリも、
自分で一から開発できるようになる訳で、(>>781が言うように)後の人生で応用が利きます。
大変ですが技術の習得をお勧めします。
0789デフォルトの名無しさん
2009/09/13(日) 19:37:05Sleep(0)を呼び出しているんじゃないのか?
Sleepに与えている時間は何ミリ秒なんだ?>>780
0790デフォルトの名無しさん
2009/09/13(日) 20:29:14サーバもクライアントも自作なのでなんでもし放題です
0791デフォルトの名無しさん
2009/09/13(日) 20:42:54ipsecとか、ssh port forwardとか。
0792デフォルトの名無しさん
2009/09/14(月) 00:00:25レスありがとうございます。
同期recvのみでもデータ受信とタイムアウト発生を待機出来るような気がしますが、
やはりselectの方が良いのでしょうか?
sleepは>>789さんの仰る通り、Win32APIのSleepを呼び出しているようです。
接続が無い場合の無駄なループを減らすためか、100ms待機しています。
しかし>>787さんのselectを使う方が理にかなっていますね。
あと勘違いしてましたが、acceptの場合は非ブロッキングやselectのメリットって多いんですね。
というか同期acceptのみだと、停止(やるとすると無理矢理かWSACancelBlockingCallかな?)や受け入れ数制限とか出来ないんですね。
>>788
おかげさまで少しだけイメージが掴めてきたような気がします。
でもブロッキングに比べて、スレッドやメモリは節約できますが、コアが多くなるほど全体的なパフォーマンスが落ちるような気もします。
その場合はある程度接続が多くなると、スレッドを増やす感じなのかな?(イベントオブジェクトの場合は必然的にそういう実装になるようですが)
おもーい腰を上げて、もう少し他のP2Pあたりのソースコードでも読みつつ勉強しようと思います。。
0793764
2009/09/15(火) 01:09:01スマン、自分はWinSockについてはまるで詳しくない。
勝手にUNIXソケットだと思い込んでレスしてた。
>同期recvのみでもデータ受信とタイムアウト発生を待機出来るような気がしますが、
>やはりselectの方が良いのでしょうか?
UNIXの場合は(シグナルを除いて)receiveではタイムアウト発生を待機できないから、
select使用が必須になる。WinSockが待機できるのなら、それで実装してもいいと思う。
自分なら(>>788で述べた)イベント待ちループ内で、すべてのイベント発生を待機させるけどね。
言い換えると、selectを使用して、イベント監視を1カ所に局所化した設計を選ぶ。
ただ、(>>783が指摘しているように)WinSockはselectのオーバヘッドが大きい。
だから、receiveで待機させる設計を選んだのかもしれない。自分に分かるのはここまで。
(UNIXであれば、それなりのリソースを用意することで、数10から数百TCPコネクションくらい
までなら実用的な性能を実現できる。シングルプロセッサの時代には多用された手法です。)
>でもブロッキングに比べて、スレッドやメモリは節約できますが、
>コアが多くなるほど全体的なパフォーマンスが落ちるような気もします。
その通りだと思う。
今でもシングルスレッド&非ブロックが多用されるのは、クライアントの開発。
GUIツールキットがあるから、マルチスレッディングが使いづらいのと、
性能や規模拡大性(スケーラビリティ)は、それほど重視されないのが理由。(Winnyが典型例かな?)
サーバ開発で採用されるのは、組み込み用途でリソースが極端に制限される場合が多い。
今時のサーバ開発では、(UNIXであっても)マルチスレッディングが一般に採用されるはず。
0794デフォルトの名無しさん
2009/09/15(火) 09:29:250795デフォルトの名無しさん
2009/09/15(火) 10:22:150796デフォルトの名無しさん
2009/09/15(火) 16:30:18マルチスレッドだと、スレッドからのプロセスのフォークが怖かったので
シングルスレッドでやることが多かったな。
今は怖くないから問題ないけど。
0797デフォルトの名無しさん
2009/09/15(火) 17:39:29たとえば210.58.02.XX君は58.697.67.XXX君の後ろで・・・とか
0798デフォルトの名無しさん
2009/09/15(火) 17:45:270799デフォルトの名無しさん
2009/09/15(火) 17:49:30acceptする場合にクライアントの選択は出来ないので、不可能。
0800デフォルトの名無しさん
2009/09/15(火) 17:57:01接続要求は 即accept → クライアントのIPをプール
予定セッション数未満ならそのまま受け付け、予定セッション数いっぱいの場合には
優先順位の低いクライアントのIPかを判定して、そいつを切断
クライアント側は再接続をトライさせる
こういう管理になるんかねぇ
0801デフォルトの名無しさん
2009/09/15(火) 18:09:36予定セッション数いっぱいの場合には、
acceptせずに放っておく方法(>>795)もあるね。
0802デフォルトの名無しさん
2009/09/15(火) 18:16:010803デフォルトの名無しさん
2009/09/15(火) 18:25:130804デフォルトの名無しさん
2009/09/15(火) 18:28:13クライアントのIPをプール って書いたつもりだったが言葉足らずだったかも
accept 直後の奴も 一旦プールの中に収めたうえで
「プールしたIP内で最も優先度の低い接続を切断しちゃおう」 という発想ね
0805デフォルトの名無しさん
2009/09/15(火) 18:30:390806デフォルトの名無しさん
2009/09/15(火) 20:19:41その理由をメッセージとして送ってから切る(send&close)ほうがいいだろね。
だって、せっかく待ち行列に並んでマダカナ・マダカナーって待ってたのに、
後から来たヤローに割り込まれてキャンセルさせられるわけだから涙目になる。
きちんとクライアントに説明してあげたほうがいいと思われ。
あと最初の受け付けを拒否される場合も、理由の説明は必要だろうね。
普通はクライアントが時間を置いてリトライすれば、いつかは成功するんだろうけど、
何か障害が発生していて、何度リトライしても成功しない状況だってありえるから。
0807デフォルトの名無しさん
2009/09/15(火) 20:54:45切断をする時点で明示的に切断されてるから
ある程度の説明責任は果たしてると思う。
なんか障害発生してたら接続された上で放置されたり
そもそも接続できないことがほとんどな気がする
0808デフォルトの名無しさん
2009/09/15(火) 21:52:03変な挙動起こしたりするんかな
0809デフォルトの名無しさん
2009/09/15(火) 21:55:060810デフォルトの名無しさん
2009/09/15(火) 22:03:30斧は待ち行列じゃないよ
排卵と精子の関係だお
0811デフォルトの名無しさん
2009/09/15(火) 22:20:33たぶんないな。
システムが割り当てたWSA系のリソース開放でしょ
だとすれば最悪メモリリーク起こすぐらいで挙動に大きな問題を抱えるものじゃないと思う。
0812デフォルトの名無しさん
2009/09/15(火) 23:35:31どういう意味?
0813デフォルトの名無しさん
2009/09/16(水) 10:23:26その後、サーバーからクライアントに返信した場合、クライアントアプリケーション側で受信できるのって
クライアントからサーバーに送信した地点で一時的にポート解放されてるから?
ファイアウォール等で受信拒否していてもつながるのも同じ理由なんだろうか
もしそうだとしたら、サーバーと通信中の2つのクライアントにお互いのIPとポートを教えて
お互いに何度かパケットを送信すれば何回目かで届き、
一度サーバーを経由するけど、そんな感じでP2Pネットワークを構築することってできる?
ためしにサンプルプログラムを組んでみたらうまくいったんだが、理論的にはどうなんだろう。
ルーターとかネットワーク環境によってはだめなんかな・・・
長文すまそ
あとスレチだったらすまそ
0814デフォルトの名無しさん
2009/09/16(水) 10:45:160815デフォルトの名無しさん
2009/09/16(水) 11:20:090816デフォルトの名無しさん
2009/09/16(水) 12:29:540817デフォルトの名無しさん
2009/09/16(水) 12:46:42セッションハイジャックとかしらべてみたらどうかな
0818デフォルトの名無しさん
2009/09/16(水) 13:05:00サーバーとの接続は公開鍵方式で、その後クライアント同士の接続はサーバーが指定した
秘密鍵で行う予定なのでその辺は問題ない…と思う
セキュリティー云々は置いといて、ファイアウォールはアプリケーション許可してもらう前提で
これで一般家庭でつながらないことは無いのかな?と思ったまでです
0819デフォルトの名無しさん
2009/09/16(水) 16:04:150820デフォルトの名無しさん
2009/09/16(水) 16:05:200821デフォルトの名無しさん
2009/09/16(水) 16:08:25何か垂れ流してるみたいで気持ちが悪い
0822デフォルトの名無しさん
2009/09/16(水) 16:20:020823デフォルトの名無しさん
2009/09/16(水) 16:23:260824デフォルトの名無しさん
2009/09/16(水) 16:31:092.液晶画面の局所的なフレネル反射の本気
3.819が光過敏性てんかんになった
4.ソケットを開いたプロセスが終了しきれずに生きている
5.知らね
0825デフォルトの名無しさん
2009/09/16(水) 16:34:400826デフォルトの名無しさん
2009/09/16(水) 16:37:460827デフォルトの名無しさん
2009/09/16(水) 16:40:410828デフォルトの名無しさん
2009/09/16(水) 16:54:180829デフォルトの名無しさん
2009/09/16(水) 20:00:09Wiresharkも回せないのか?
0830デフォルトの名無しさん
2009/09/17(木) 09:07:17なんでそういう単語を照れもなく使っちゃうレベルの人が
Winsock なんかに手ぇ出すかなあ。
0831デフォルトの名無しさん
2009/09/17(木) 18:38:250832デフォルトの名無しさん
2009/09/17(木) 20:38:44こいつにレスポンスコード302返したらどうなるん?
0833デフォルトの名無しさん
2009/09/17(木) 21:03:230834デフォルトの名無しさん
2009/09/17(木) 21:36:18セッションクッキー情報はTemporary Internet Filesに作られないのでせうか?
0835デフォルトの名無しさん
2009/09/17(木) 21:49:580836デフォルトの名無しさん
2009/09/17(木) 22:40:050837デフォルトの名無しさん
2009/09/18(金) 03:01:400838デフォルトの名無しさん
2009/09/18(金) 15:55:07サーバープログラムに、クライアント数制限をつけたいと思っています。
例えば、10人までしか接続が確立できない。という類です。
FD_ACCEPTが呼ばれた際、acceptをします。
定員を超えていたら、次の行でacceptから帰ってきたSOCKET(正常なもの)をshutdownし、closesocketしました。
そうしたところ、どうやらクライアントに切断したことが伝わらないようで、クライアントのrecvがSOCKET_ERRORを返してくれません。
FD_ACCEPTを抜けた後、別の場所(メインループなど)でshutdown & closesocketした場合は伝わるようです。
・FD_ACCEPT内でclosesocketしてはダメなのでしょうか?
・そもそも上限に達していたら、acceptしないという方法はないのでしょうか?
ご教示よろしくお願いいたします
0839デフォルトの名無しさん
2009/09/18(金) 16:20:07・recvが0を返したら、通信終了でいいんじゃない?
> ・そもそも上限に達していたら、acceptしないという方法はないのでしょうか?
それぞれのクライアントに対する処理は非同期で動作してる前提で話すけど、
acceptする前に、セマフォとかで調停する。
0840デフォルトの名無しさん
2009/09/18(金) 16:35:28お返事ありがとうございます。なるほど。SOCKET_ERRORではなく、recvの返り値が0の場合も切断なのですね。
調べてみたところ、recvが0を返すのは「正常な終了」が行われた時とありました。
どうもありがとうございます。
0841デフォルトの名無しさん
2009/09/18(金) 16:40:43aaceptする前に既にクライアントには受理されたことになってしまうので
http://www.kt.rim.or.jp/~ksk/sock-faq/unix-socket-faq-ja-3.html#ss3.3
acceptする前に調停しても、クライアントには伝わらないんじゃないかな。
acceptしないだけだと、たぶんクライアント側をしばらく待たせることになるので
それよりは一旦acceptだけしてから切断するほうが親切じゃないかな。
0842デフォルトの名無しさん
2009/09/18(金) 17:07:45ありがとうございます。
最初から拒否しておく。ということはできないのですね。
意外でした。
・FD_ACCEPTの中で切断しても大丈夫
・上記の結果、クライアント側のrecvの返り値が0になる
のが確認できました。
0843デフォルトの名無しさん
2009/09/20(日) 19:01:52既に接続が確立されてる相手からの送信データを待ちつつ
新たな接続が無いかどうかチェックするにはどうしたらいいの?
0844デフォルトの名無しさん
2009/09/20(日) 19:47:02acceptでブロックされたくないなら
該当descriptorをselect/pollすりゃいい
0845デフォルトの名無しさん
2009/09/20(日) 19:47:03接続待ちになるのはacceptね。
> 既に接続が確立されてる相手からの送信データを待ちつつ
> 新たな接続が無いかどうかチェックするにはどうしたらいいの?
接続が確立した相手用に新しいスレッド起こすか、
select使って複数のソケットに対してデータ待ちするか。
Windowsなら他の方法もあったかもしれない。
0846デフォルトの名無しさん
2009/09/20(日) 19:47:200847デフォルトの名無しさん
2009/09/20(日) 20:06:14select/pollのとこでフリーズしてしまいましたが。。
0848デフォルトの名無しさん
2009/09/20(日) 20:30:14別に>>844,845は、特に変な事は言っていないと思うけどな。
>>845に細かすぎる指摘(改善)すると、以下のようになるけど。
>select使って複数のソケットに対してデータ待ちするか。
==>select使って複数のソケットに対してデータ受信と接続を同時に待つか。
文句付けるなら、自分ならこうだ!ってのをレスしたほうがいいと思われ。
0849デフォルトの名無しさん
2009/09/20(日) 20:30:42素人でしゃばんな
0850デフォルトの名無しさん
2009/09/20(日) 21:15:37それは使い方が悪いからだろう。たぶん。
0851デフォルトの名無しさん
2009/09/21(月) 02:17:11夏厨は土に返ったはずであるが?
にーとさんかな?
0852デフォルトの名無しさん
2009/09/21(月) 07:09:590853デフォルトの名無しさん
2009/09/21(月) 12:58:080854デフォルトの名無しさん
2009/09/21(月) 14:22:25言語とかトラフィックパターン依存になるから、
プリミティブなソケット以上の共通化は不可能なのかね。
スレッドプールの共通インターフェイスが先か。
0855デフォルトの名無しさん
2009/09/21(月) 15:57:500856デフォルトの名無しさん
2009/09/21(月) 16:24:00俺のとこじゃフリーズしなかった
0857デフォルトの名無しさん
2009/09/21(月) 18:27:22select/pollのとこで止まってしまって先に進まなくなるのです。
0858デフォルトの名無しさん
2009/09/21(月) 19:13:010859デフォルトの名無しさん
2009/09/21(月) 19:19:500860デフォルトの名無しさん
2009/09/21(月) 21:17:270861デフォルトの名無しさん
2009/09/21(月) 22:26:20どこまでライブラリに機能を提供させるかという、境界線を引くのが難しい気がする。
トラフィックパターンが一方向の要求/応答に限定できるならRPC(JavaならRMI?)あるいは
HTTPライブラリで済むけど、わざわざソケットに手を出すのは、それ以外のパターンが
必要になる、ある程度複雑な(高機能な)アプリケーションを開発するケースだと思う。
ただ、そうなると、メッセージの衝突/送信権、分割/連結、優先制御/流量制御なども、
ライブラリが提供すべき機能要素として要求される(要求する人もいる)だろう。
またマルチスレッド/マルチプロセス/ファイバに関しても、どこまでライブラリで
対応させるべきか、人によって意見は分かれるはず。
だから、最終的には必要最低条件を満たしたソケットで落ち着いてしまうのだと思う。
個人的にはレコード指向(TCPのメッセージ境界対応)で全二重な機能だけを提供し、
あとは上位レイヤのプロトコル(アプリケーション)の実装にまかせる、軽いライブラリが
あってもよさげだと思うんだけどね。
0862デフォルトの名無しさん
2009/09/22(火) 15:55:58よかったね。
コード見せてくれないとわからんがな
0863デフォルトの名無しさん
2009/09/23(水) 16:30:480864デフォルトの名無しさん
2009/09/23(水) 16:35:36「readして読んだバイト数が0の場合」ってのじゃなくて、なんかのひっかけ?
0865デフォルトの名無しさん
2009/09/23(水) 16:35:440866デフォルトの名無しさん
2009/09/23(水) 16:51:050867デフォルトの名無しさん
2009/09/23(水) 16:55:47Unix 系の EBADF, ENOTCONN, EINTR, EFAULT は
相手がクローズするしないに関わらず発生する
0868デフォルトの名無しさん
2009/09/23(水) 19:07:23EINTR以外はプログラムバグじゃないの?
0869デフォルトの名無しさん
2009/09/23(水) 19:24:59そうだけど、そんなん言ったらECONNRESETだけじゃないか
明示的にエラーになってクローズされてるのは
0870デフォルトの名無しさん
2009/09/23(水) 21:32:37ですな〜
でも、recvが想定外なエラーを返した時点でそのソケットは捨てるしかないけど。
0871デフォルトの名無しさん
2009/09/24(木) 14:51:00一つのソケットでrecvとsendしたい場合はやっぱり非同期にするしかないのか・・・
0872デフォルトの名無しさん
2009/09/24(木) 15:23:51危なくはないと思うが。shutdown/closeさえ気をつければ。
ただ、recvとsendを別スレッドにすると、スレッド間でデータの共有が
必要になって面倒だから、普通はシングルスレッドで作るんじゃねえか?
完全にスレッドが分離してるんなら、別々でも無問題だろ。
0873デフォルトの名無しさん
2009/09/24(木) 15:24:47すくなくとも *nix は大丈夫なもよう
0874871
2009/09/24(木) 15:46:39レスありがとう
Winsock中級者向けの議論からも次の様な一文を発見
一方のスレッドが send() を呼び出し、別のスレッドが同一のソケットに対して recv() を呼び出すのは安全である、という伝説があります。
しかし私はこれを確認したことはありません。より堅固な情報やデモンストレーション用のコード、さらなる伝説などがあれば、教えていただけると幸いです。
まあとりあえず大丈夫だろうってことですね
0875デフォルトの名無しさん
2009/09/24(木) 15:50:58安価ミス
0876デフォルトの名無しさん
2009/09/24(木) 22:21:00Solarisは不定期にハングしてたよ
今はどうだかしらんけど・・・
0877デフォルトの名無しさん
2009/09/25(金) 12:10:34close後にレスポンス着てるみたいなんだがshutdownしないとだめ?
0878デフォルトの名無しさん
2009/09/25(金) 12:17:150879デフォルトの名無しさん
2009/09/25(金) 12:19:31送信スレッドと受信スレッドが別とかって話か?
必要なレスポンスなら何とかしてやるのが筋だろ?
送信側: SHUT_WR 送信で終了
受信側: 読込みバイト数0になるまでレスポンス読んで close
とか………
つか、プロトコル設計見直した方がええんちゃうか?
0880デフォルトの名無しさん
2009/09/25(金) 13:55:05送信パケットもモニタできるようにするのは不可能ですか?
WinPcapドライバを使えば送信パケットもモニタできるのだけど・・
0881デフォルトの名無しさん
2009/09/25(金) 21:03:37できんことは無いけど、それを作り上げていくと
WinPcapドライバが出来てしまうわけで
意味無いよな
0882デフォルトの名無しさん
2009/09/26(土) 20:27:520883デフォルトの名無しさん
2009/09/26(土) 20:46:56あーるいーしーぶい
■ このスレッドは過去ログ倉庫に格納されています