7 :
1:2007/02/09(金) 23:15:50
乙
教えてください。
send/recvを使ってHTTP通信したいのですが、ブロックしてしまうのを回避するために
・send/recv前に毎回selectして調べる
・非同期でsend/recvしてh_errorを調べる
の方法は適切ですか?
・非ブロックソケットを使う
>>11 ・無限ループのスレッドでずーっとread、メインはセマフォ待ちで待機。
・改行の受信か相手側のクローズを検知したらセマフォを解放
これが正しいモデルだと思うけど、どうよ。
無条件に正しいモデルなんてものはない。
無限ループのrecvなんて、最悪だな。
read/recvはCPU負荷率が下がるので逆に推奨。
最悪なのはI/O待ちもsleepもない計算だけのループ。
I/O待ちだけでブロックしてるようなスレッド作ると、他所から
そのスレッドを綺麗に終了させる手段がないじゃん。
イベントとI/Oの両方を待機させるような作りにするのが定石じゃないの。
19 :
11:2007/02/17(土) 17:45:45
レスありがとうございます。
後出しになって申し訳ないのですが、実はApache + C++CGIとして動作させています。そのため、スレッドの生成は避けたいと思っています。
CGIの待機中プロセスが増えすぎてしまわないためにタイムアウトを設けたいと思って質問しました。
少なくとも毎回selectするくらいなら非ブロックモードにするべきのようですね。
非ブロックでsend/recvし、ソケットが閉じられるまでループさせる方法で試してみます。
> イベントとI/Oの両方を待機させるような作り
そうそう、
socketのイベントとpthread_cancelを同時に待つ方法が知りたい。
>>19 > 少なくとも毎回selectするくらいなら非ブロックモードにするべきのようですね。
なことはない
何でRFCはあんなに読みにくいのかと。
読みやすいよ。規格書としては抜群に。
ITU, IEEE, ISOに比べればね。
Can't Conceive Intelligent Thoughts Today
Content-Dispositionでさあ、IEってfilename="c:\abc\def.txt"
みたいに送ってくるけど、\はquoted-pairになるから、これって違法な
気がするんだが・・
プログラムとちょっと外れるけど
環境はWindowsXPです
名前解決を変更するのにHostsをいじればいいわけですが
ドメインではなくて実際のIPにフィルターかけることって出来ますかね?
192.168.1.90 -> 192.168.1.100
90へのリクエストはすべて100へ行くようにしたいわけです
ソケットフックするしかない?
static arpを登録すればいける気がする。
(IP->IPのマッピングじゃないけど。)
書き込んでから気づいた。受け取り側がよっぽどアホでない限り、
自分のIP宛でないパケットが来たところで無視されるのがオチだな。
・/28あたりでネットマスク切って、あとは自力構成したルータの
パケットフィルタで書き換える
・振り替えを実行したいマシン毎で、192.168.1.90に対して、192.168.1.100のMACを
static ARPとして設定する。そのうえ、192.168.1.100のマシンで、ループバック
インターフェースに、192.168.1.90/32を割り当てる。100のマシンのホストモデルが
「強力」なら「弱い」にしておく。
くらいしか思い浮かばないな。
というか、それがいわゆるNAT。
宛先を書き換えるわけだから、逆NATでないの。まーどーでもいいけど。
ちなみに100のほうは変動するので
90内でだけで解決しないといけない
ジャイアン乙
>>27 リクエスト元が192.168.1.90、100と違うサブネットなら、境界のルータで
NATかければいい。
同じサブネットなら、無理やりな方法になるけど
>>30 かな?
>>32 (NAPTじゃない)NAT、それも固定NATなら、対称なんだから逆も何もない。
100のほうは正確にはグローバルIPになる
ローカルから接続する対象をリアルタイムで変更したいわけ
ソフトによってはIP固定で通信してるからそれに対応したいということ
NATってあて先変更できたっけ?
90のほうにNATソフトいれたら出来るんだっけ?
そういう機能があるソフト知ってたら教えて下さい
技術的に出来ることは十分わかってるんですが
ソケットをフックするよりドライバ書いてるほうがはるかに手間がかかるので
NATの原理で出来るというアドバイスは愚の骨頂です
最初に書いた通り、こちらの最も望むものはフックするより手間の掛からない方法です
>>39=
>>27なの?
馬鹿だなあ。
知識足りないんだから、大人しく教えを乞えばいいのに…
なんだなんだ、ネトゲの改造か何かか?
チートツールじゃないですよ。健全な目的です。
45 :
43:2007/02/27(火) 07:27:19
ありがとうございます。
というかまだ全然プロトコル解析の段階にいってません・・・orz
メディアプレイヤーで以下のアドレスを再生させると
mms://wms.g2.cdn.bcast.co.jp/yahoo/ystream/kad/10193/kad1019300001100000b929.asf?session_id=b4d2575ccae7b6b454cece0e68ea0860&product_id=
取得パケットの中には
202.93.94.14
という外部アドレスだけが見つかりました。
ttp://www.cman.jp/network/support/ip.html で調べたところ、
wms.g2.cdn.bcast.co.jp
というのは
202.93.94.16
というアドレスであると出たのですが
逆に
202.93.94.16
を調べたら
wms06.g2.bbt.bcast.co.jp
と出ていました。
46 :
43:2007/02/27(火) 07:28:53
202.93.94.14
を調べたら
wms04.g2.bbt.bcast.co.jp
と出ていました。
でももう一度改めてパケット取得してみたら
202.93.94.15
というアドレスだけが見つかりました。
wms.g2.cdn.bcast.co.jpというドメイン名からは
正確なIPアドレスはわからないものなのでしょうか?
% dnsip wms.g2.cdn.bcast.co.jp
202.93.94.16 202.93.94.15 202.93.94.18 202.93.94.17
「正確なIPアドレス」の定義がよくわからんが、1つのDNS名が
複数のIPアドレスを持つのは、負荷分散的によくあること。
マルチスレッドのスレからきました。
winsockのプログラミング勉強してます。
recv関数でよくselect使用して、タイムアウト処理すると思います。
同じようにして、accept関数のタイムアウト処理をしたいと思ってますが、
accept関数呼ぶ前に、select関数使えないんでしょうか。
FD_ZERO(&readfds);
FD_SET(soc,&readfds);
select(width,&readfds,NULL,NULL,&timeout)
socは、きちんと渡せていたんですが、接続試しても
select抜けられずに、全部タイムアウトになります。
accept呼んでからじゃないと、ソケットの読み取り可能か
わからないのでしょうか。
やりたいこと伝わりませんでしたら、
補足させていただきます。
selectの最初の引数が気になるけど、それでOK.
>>50 WSAStartup->socket作成->bind->listen->accept->select呼んでrecv
よくあるrecvのタイムアウトは、こんな順番だと思います。
accept関数もずっと待ち状態になるので、recvのときと同じように
タイムアウトの機能を、追加できないかと考えてます。
WSAStartup->socket作成->bind->listen->select呼んでaccept->recv
なぜか、クライアントから接続してもselectから、抜けられないんです。
タイムアウトだけでしか抜けられません。
・acceptした後でないと、ソケットの読み取り可能かわからず
select関数使え無い。ということがあるのかと思いましたが
気のせいでしょうか。
>selectの最初の引数が気になるけど、それでOK.
selectにも、きちんと引数渡せてるようなので、
どこがおかしいのかわからないです。
もうちょっと、ポイントしぼれるようにがんばってみます。
レスありがとうございました。
51です。
あれれ、ソースコード特にどこも変えた覚えないのですが、
listenのときのソケットディスクリプタと
acceptの返すディスクリプタの値比べて、
同じ値が表示されてるの確認作業したりしていたら、
いつのまにかタイムアウトの処理できていました。
んー、ほんとにどこも変えた覚えは無いのですが・・・
原因説明できなくて、すみません。
acceptもrecvとほぼ同じコードで、タイムアウト処理できました。
どうもお騒がせいたしました。
ありがとうございました。
acceptのタイムアウトが出来ると、
アプリの終了処理の時に使えますね。
poll( )なプログラムを、pollを持ってないWIN32環境にselect( )で移植しています。
selectを使ったpollの実装ってどこかに転がってたりしませんでしょうか?
ぐぐったのですがいいのがなくて。
既出だったらスマソ
pollって1024以上オッケーだっけ?
>>54 WSAEventSelectで登録して、WaitForMultipleObjectsがWinSockの作法。
WaitForMultipleObjectsの上限に引っかかるぐらいのスケールなら、IoCompletionPort。
>>54 手抜き移植でソースをなるべく変えずにpoll()を使いたいってこと?
cygwinは、WaitForMultipleObjects()を用いてselect(), poll()を
エミュレートしてるはずなので、cygwinのソースを読むと良い。
つか、移植の手間を一切掛けたくないのなら、ぶっちゃけcygwinで
コンパイルすればいいだけなのだが。cygwin1.dllには依存するけどな。
一から自分で書くなら、
>>56の言うようにIOCPがWindowsではもっとも
効率がよく、しかも色々応用が利いて便利だ。NT系のOSでしか使えないが。
書籍スレで聞くべきかも知れませんが、
中級ネットワークプログラミングみたいな本で
お勧めの本はありませんか?
英語でも構いません。
amazon.co.jpや、お勧め書籍スレ/ページは色々見てみましたが
基礎的なソケットの使い方などの本が多いようです。
それなりに実用的なネットワークソフトの解説のようなものがあれば幸いです。
ソース嫁ってことになるのかも知れませんが、よろしくお願いします。
59 :
デフォルトの名無しさん:2007/03/04(日) 18:32:12
板違いなのですが、おそらくこちらのスレの方のほうが詳しいと思いますので、
質問させてください。
環境:Windows2000/XP
会社で営業部ドメイン(EIGYO)と、技術部(GIJYUTU)があります。
自分のPCは、GIJYUTUに属してます。
UNC(\\EIGYOU\フォルダ名の形式)を使って、営業部ドメインの
共有フォルダにアクセスする事は出来るのですが、
「マイネットワーク」を開いて、営業部ドメイン(EIGYO)にアクセスする事が
出来ません。営業部ドメイン(EIGYO)自体表示されない。
「マイネットワーク」に、自分が所属していないドメインを表示させる方法って
ありますでしょうか。
>58
プロトコルをヘッダ込みで実装してみるとか
メーラーを作ってみるとかするのがいいと思う
プロトコルのコマンドやフォーマットはネットで探せるし
Etherealを使えばアプリがやり取りしているパケットも見れる
ドライバ、apacheなどのモジュールを作るのもいい
中級を目指すならこれから作るものを定めておいたほうがよいのでは
などといってみる
レベルが上がるにつれて道程は細分化していくから
\\EIGYOU
54です。
>>56 >>57 dクス
手抜き移植と言うか、今後のメンテを考えて、
unix/linux版とwin版でできるだけ統一ソースにしておきたいんですよねぇ...
socketのラッパーみたいなのがあるといいなぁとオモタのですが、
自分で書くことにしますです。
$(GLIBC)/sysdeps/unix/bsd/poll.c じゃダメかい? > selectのpollラッパ
>>63 $(GLIBC)/sysdeps/unix/bsd/poll.c 使えそうですね。どもです。
>>65 for (i = 0; i < nfds; ++i) {
fds[i].revents = 0;
if (!cygheap->fdtab.not_open (fds[i].fd)) {
sysdeps/unix/bsd/poll.c ってこんな実装になってるんですね... 総当り(笑)
やはり発想変えてpollになっているところをselectに直すほうがいいのかなぁ。
教えてエロイ人
根本的にlibevent使って書くとか、
どこでも使えるselectにするとか
するしかないんじゃないの。
BASIC認証について質問です。
サーバのあるディレクトリにアクセスすると、はじめの1回目の認証で
ダイアログボックスが表示されますが、2回目以降はそのディレクトリ以下に
アクセスしても表示されなくなります。
この機能は、サーバとクライアントどちらの機能で実現されているのでしょうか。
Basic認証では、ログインではなくて、毎回ID、PASSを送信しているということなので
「サーバの方では特に何もせずに、クライアントの方でアクセスしたURLのアドレスを記録しておいて、
2年目以降は、その下のディレクトリにアクセスするときは、初めからリクエストのヘッダに
”Authorization: Basic hogehogehoge”を付けるようにしている。」というふうに考えたんですけど、
どうなのでしょうか。
よろしくお願いします。
>>68 パケットモニタで調べてみますた。
クライアント側で毎回送ってますね。
Authorization: Basic hogehogehoge
をつけないでGET/POSTすると、応答に
HTTP/1.1 401 Authorization Required
WWW-Authenticate: Basic realm="Login"
みたいなのが帰ってきます。
>>69 調べていただいてありがとうございます。
BASIC認証で一回アクセスしたら、何らかの仕組みで、
ブラウザの方でそのアクセスしたURL(ディレクトリ)を覚えておいて、
2回目以降そのディレクトリ以下にアクセスするときは、自動的に
ヘッダーにAuthorization: Basic hogehogehoge を付けてるんですね。
ふむふむ。それで、2回目以降はダイアログが出てこなくなると。
BASIC認証できるhttpサーバもどきを、勉強の課題で作ってますが、
サーバ側でなにか大掛かりな仕組みでもあるのかと、心配になりまして。
パケットモニタというのも、知らなかったので勉強になりました。
どうもありがとうございました。
>>70 そういう調査技能もあると便利だが
HTTPに関してはRFC2616とかに全部定義されている
winsockの勉強中に疑問に思ったことの質問です。
sockB = accept(sockA, &addr, &size)のような形で子スレッドで
動かしていて、acceptでブロックされてます。アプリケーション終了時に
親スレッドでclosesocket(sockA)という風に処理していいのでしょうか?
>>72 「処理していいのでしょうか?」の意味が、
処理して正しく動作するのでしょうか?
→知らん。試せばわかる。
>>72が期待している動作(acceptを抜けるか/抜けないか、
抜けるときのsockBの値、GetLastErrorの値、etc) を知りようがないのに
正しい動作も何もない。
一般的にそのような処理をするものなのでしょうか?
→マルチスレッドを真面目に考えたプログラムなら、イベント使って、
非同期Acceptをするので、このような状況に陥らない。
>>73 回答ありがとうございます。
もっとマルチスレッドやイベントについても勉強しないといけないようでした。
レジュームダウンロードについて教えてください。
サーバ側:ダウンロードしたファイル
クライアント:ダウンロードの途中のファイル
こういう状況だったとします。
1.接続しクライアントに途中のファイルがあるかどうかを確認。
2.クライアント:ファイルを読み込んでハッシュ値を出し、「ファイルの名前:読み込んだ文字列の長さ:ハッシュ値」を送信
3.サーバ:「ファイルの名前:読み込んだ文字列の長さ:ハッシュ値」を受信します。
4.サーバ:読み込んだ文字列の長さ分(Nとします)、ファイルから文字列を読み込んでハッシュ値を出し、クライアントからのハッシュ値を比較
5.ハッシュ値が一致した場合は、seek関数でファイルのポイントをN個移動して、そこから読み込んで順番にデータを送信
こういう感じでしょうか?
修正、追加する場所、その他気をつけることなどありましたら
アドバイスよろしくお願いします。
なんでハッシュが出てくるのか分からん
Range:bytes=100-
REST 100
FTPの場合REST 100で100バイト目から取れる根拠は実はRFC959にはないけどな。
もっと新しいRFCがあるのか?
>>76 同じファイルか、確認のため比較する容量が大きいと転送が大変だと思いまして。
>>76 >Range:bytes=100-
httpのヘッダー情報に、こういうのがあったとは。
でもブラウザは、途中からのものをダウンロードできても、
上書きだけみたいですね。
>>78 ttp://www2s.biglobe.ne.jp/~hig/tcpip/HostReq_Appl.html#HREQAPP_4_1_3_4 サーバ FTP は、データストリーム中の都合の良い箇所に再開マーカ <ssss> を付ける
buf="hogehoge";を送信するとき、
"<ssss>hogehoge"を送信して、
・サーバ側では、send()するとき、<ssss>をbufのどこか適当な位置に挿入して送信
・クライアント側では、recv()するたびに、制御ファイルの(ssss,rrrr) を更新。
・再開するときは、<ssss>を送信。
とリンク先見てこいうことかと想像してたんですが、実際の実装で
送られてくるクライアントに、送信される文字列bufって、どんな形なんでしょうか。
RFCでどこに書いてあるのか探してるんですが、よくわかりません。
80です。
通信の中身は、パケットモニタで見るという方法がありました。
82 :
デフォルトの名無しさん:2007/03/10(土) 09:15:33
>>80 > とリンク先見てこいうことかと想像してたんですが、実際の実装で
> 送られてくるクライアントに、送信される文字列bufって、どんな形なんでしょうか。
> RFCでどこに書いてあるのか探してるんですが、よくわかりません。
とにかくRFCを読んで。
解説ページに惑わされないで。
>>83 おお。5.1でSTREAMモードでの再開が規定されとる
> Expiration Date: March 2003
が気になるけど
負荷おおすぎねえ?
>>86 確かに大きそう。まあSSL通信に比べれば
そんなでも、ないかもしれないけど。
アホか
手順4見てみろ
DDoSされたら終わりだな
ハッシュ値持たせるならサーバ側はブロック単位で最初から持っとけよ
クライアント側で計算させて一致しないのだけやり直しが普通の発想だろ
同じファイルかどうかなんてクライアントがETagでも覚えとけよそんくらい。
ブロック毎に32bitCRC値を持たせるとしたら、
ブロックの長さはどれぐらいが適当でしょうか。
仮に64kByte毎だと1MB辺り64Byteで済みますが、
これは冗長でしょうか。
残りの長さの全部のハッシュを求めないで、
サーバとクライアントでそれぞれ2,3箇所ピックアップして、
ハッシュ求めれば十分じゃん。
あとダウンロードは、なんも処理しないでいいんだし。
ただ、これをいうと、ハッシュじゃなくてもいいんだよな。w
どれだけ'同じファイルであるかの確かさ'を求めるかだ。
毎回なんか処理しながらダウンロードって、しないに越したことは無いでしょ。
突っ込みの嵐の予感。
>>94 > ただ、これをいうと、ハッシュじゃなくてもいいんだよな。w
>>76
>>93 ブロック長が長くなるほど衝突が増える。
ブロック長が長くなるほど再送に無駄が増える。
後は自分で考えて。
>>94 普通、まずサイズや最終更新時間を調べるでしょ。
そんなわけでFTPだってSIZEとMDTMコマンドがある。
udpでメッセージを交換する簡単なプログラムを作っているのですが、
可変長文字列で詰まってしまいました。
struct message{
int size;
char buf[1];
}
struct message *p;
p = (struct message *)malloc( sizeof(struct message) + strlen(input) );
送信したい文字列をinputに格納して、その長さに合わせてこのmessage構造体をmallocしているのですが、
受信側ではなぜか文字列が途中で途切れてしまいます。
可変長を実装するにはこのやり方は間違っているのでしょうか?
MTUよりでかくなってないか?
100 :
98:2007/03/13(火) 01:03:07
MTUが1500で、送信サイズが20byte程度でしたので、MTUを越えてはいないと思います。
今色々デバッグしてみたところ、sendtoで送信できているサイズが、sizeof(struct message)と同じ値でした。きちんとmallocはしているはずなのですが…
送信側のsendのところと受信側のrecvのところのコードを晒せ
102 :
98:2007/03/13(火) 02:16:30
sendとrecvのサイズを設定する引数が間違っていました。
send:
sendto( s,p,sizeof(struct message) + strlen(input),0,(struct sockaddr *)pfrom,fromlen );
recv:
recvfrom(s,p,sizeof(p)+20,0,(struct sockaddr *)pfrom,fromlen);
といった感じに改造したところ、短いメッセージならきちんと受信できるようになりました。ただ20という数字が適当なので、この部分をきちんとinputの長さに合わせたいです。
sizeof(p)がstruct message *pなんだろうなぁ
C言語のテキスト見直ししる。
104 :
98:2007/03/13(火) 11:23:32
受信側をsizeof(struct message *p)としましたが、やはり適当な値を受信サイズに加算しないと駄目なようなので、この方法でやろうと思います。
ありがとうございました。
>>103 > sizeof(p)がstruct message *pなんだろうなぁ
これは
>>98のミス原因をつぶやいただけだろ。
Cの勉強し直してくれ。Cが分からないから
>>103を誤読する。
>>103 recvfrom(s,p,sizeof(p)+20,0,(struct sockaddr *)pfrom,fromlen);
で、pの宣言がstruct message *pなら
sizeof(p)+20=24ぐらいになるってことでしょ?
paddingとか32bit環境とかは置いといてね。
> これで出来ることは増えないが、
C99以前は配列の最終要素を踏み越えるのは厳密には未定義じゃなかったっけ
UDPはパケット境界保持されるんだから小細工しなくていいんでない?
UPNPのnat traversalで空けたポートに
"本当に"外部ネットワークからアクセスできるか確かめる方法って
外部にそれようのサービス立てておいてそれを叩くしかないよね?
111 :
デフォルトの名無しさん:2007/03/13(火) 21:03:34
すまん言い方が悪かったかな
ポートを空けたプロセス自身から確かめる方法
ちょっと基本的な事ですいません。
[サーバ(accept側)]−[クライアント(connect側)]
こんな感じで繋がっている時、
1秒間にサーバからsendできるデータの限界量=上り帯域
1秒間にクライアントからsendできるデータの限界量=下り帯域
という概念で合ってるでしょうか。
sendがsocket apiのsendのことをさしているなら違う。
sendはtcpの送信バッファにコピーするだけ。
udpだったらクライアントからはsendできたように見えても
どんどん捨ててるだけということもあり得るし
116 :
113:2007/03/15(木) 20:53:07
では、
1秒間にサーバ/クライアントから送信できるデータの限界量=上り/下り帯域(/sec)
という事でしょうか?
ごはんつぶは糊として使えるが
糊=ごはんつぶというわけではない
118 :
58:2007/03/16(金) 00:04:01
>>60 さんざん遅れて申し訳ありませんが、ありがとうございます。
しばらく仕事に忙殺されていて死にかけていました。
119 :
113:2007/03/17(土) 02:47:41
なんとなく自己解決しました。
ソケット通信でどっかのHPのCGIに引数を渡すときはどういう応答すればいいんですか?
HTMLで言うところのformからPOSTでCGIを呼ぶってことです。
RFC 2616を読む
122 :
デフォルトの名無しさん:2007/03/18(日) 09:58:27
ここってライブラリの質問もあり?
前スレでOpenSSLの話はダメという結論になった
じゃあ、このスレ限定でおk
>121
まとめてください。
おらさっさとまとめろやクズ。
みなさん。スルーで。
急ぎませんので、今日中にまとめておいてください。それでは。
わろたw
windowsとlinuxの間で、C/C++でソケットプログラミングしてます。
チャットソフトです。
・print、strcpyとか気を付けるのと、ほかになにかあるでしょうか。
・もしも、WEBサイトに文字列を表示させる場合は、メタキャラクタのエスケープ処理ですよね。
検索したところ、これぐらいかと思ったのですが、まだまだたくさんあるでしょうか。
アドバイスよろしくお願いします。
>>131 ありがとうございます。
参考にさせていただきます。
便乗質問させてください。recv関数は受信される最大サイズが
決まってると思いますが、プログラミングしてて
長さがわからなくなるときって、どんなときですか。
日本語でおk
つかマジで機械翻訳なのかな
TCPなら繰り返し受信すればいい
UDPだったら1つのパケットに入りきらないメッセージが来ること自体あり得ない
>>133 長さがわからなくなるときは、無い
長さは必ず返却される
>>136 レスありがとうございます。
ネットワークプログラミングでは、バッファ・オーバー・フローは
気にしなくても大丈夫なんでしょうか。
気を付けて使ってるのかわからないですが、猫でもわかるとか、
他の本でもstrcpy使用してみるみたいです。
strncpy、snprintfは全然見ないような。
返された長さにもとづいてやればオーバーフローしないよ
長さを無視してるとダメだけど、
それはネットワークに限った話じゃないし
>>137 バッファオーバーフローは無論あってはならない。特にネットワークプログラミング
においては重大なセキュリティホールに繋がりかねないので、強く意識すべき。
C++を使えるのなら、Cなんぞ使わずにstringやvector<>を使うことを薦める。
ていうかさ、そんな事を質問している時点で
基本を何も分かってないって事だろ。
まず系統的に解説してある入門書読めよ。
サンプルソースうpして聞けばいいよ
>>138-141 レスありがとうございます。
>それはネットワークに限った話じゃないし
>C++を使えるのなら、Cなんぞ使わずにstringやvector<>を使うことを薦める。
とても勉強になりました。ありがとうございました。
webアプリはクライアントがどのプログラムからhttpリクエストを出してるかということを
判別できるんですか?
ブラウザ(IE)に偽装した形でhttpリクエストを出したいんです。
>>143 ajax使うしかないな
だが単純に普通にIE使ってたら最初の一発目は偽装不能
ひとつのコネクションでデータの送信と待ちうけを行うには
ポーリングするのが一般的でしょうか?
俗に言うselect系
selectもブロックしてしまいますよね?
ブロックしちゃうと任意のタイミングで送信ができないと
思うわけです。
selectはポーリングにも使えるが?
送信可能な時はブロックしないで戻るしね。
selectの改良版はpollって名前だしね。
ちょっと詳しく教えてくれないか?
>>150 その任意のタイミング発生装置(ttyとかXのイベントとか)も
selectに含ませてブロックさせる。
何、通りすがりのサラリーマンさ。 単身赴任のね
>>157 すみません。本当はよく意味がわかってません。
しかーし、外部からselectを抜けさせればよいということですよね!
スレッド1:selectで受信待ち
スレッド2:問答無用でsend
1つのコネクションを複数のスレッドから使えるんだっけ?
>>162 今解らないことだらけでしょ?>プログラム作ってて
ソケットとかスレッドとか。
もしそうなら本買って勉強したほうがいいと思うよ
165 :
デフォルトの名無しさん:2007/03/29(木) 12:01:30
女(socket)は一人、男(thread)が複数。
同時に複数の男が出し入れすることはできない。
一人がIOしているときは、他の奴が待つように作らないとバグるよ。
>>165 その説明だと、1 socketに対し、3 thread同時にI/Oできるように読めるが?
また、thread同士でもI/Oできることになるので、適当な例えではない。
168 :
デフォルトの名無しさん:2007/03/29(木) 12:33:50
3Pはできたとしてもそれでも「同時に」IOできるのは一人の男と言いたかった。
(もう一つ穴があるだろ、はなしね)
socket自体はスレッドセーフではないが、スレッド間で同時にIOを
行わないように制御すれば、複数スレッドで単一socketを使うことは可能じゃね?
しかし、それでもデータ内容がごちゃごちゃになる可能性があったりするし、
あまり良い方法とは思わないが。
誰の子供かわかんな〜い、になっちゃう。
169 :
165:2007/03/29(木) 12:37:39
あ、165=168 ね
さて、そろそろパケットをティッシュに送信してから寝るかな
winsockでTCP通信するプログラムを作ってますが、クライアントがconnectする時に
接続先のIPアドレスに自分のマシンのプライベートアドレス指定しているときは、正常に動作しますが
グローバルアドレスを指定すると、connectからエラーコード10061 (接続が拒否された)が返ってきます
Windowsファイヤウォールによるブロックは、されてない様子です
ネットワーク初心者ですが、どういうケースが考えられるでしょうか
よろしくお願いします
173 :
172:2007/03/31(土) 08:18:29
自分自身のグローバルIPには接続できないって事ですかね
テストを行うには、リモートマシンを使わないといけないんでしょうか
ルータやファームのバージョンによるのでは
うちはファームのバージョンあげたらできるようになった
175 :
172:2007/03/31(土) 10:20:27
ポート4123番を開放して、自分のマシンでサーバを起動して、外部からクライアントで接続を試してもらったんですが
同じくconnectでエラーコード10061が発生します。何がいけないんでしょうか
サーバって何?自作?
もしそうならbind呼び出しのところのコードを晒せ
>>172 NATとかIPマスカレードの問題では。あるいはルータに
折り返し機能がないか(
>>175はこの問題と関係ないが)。
どっちにしても、ルータの設定の見直しが必要だと思います。
178 :
172:2007/03/31(土) 11:30:34
ポートを開放できてないのが原因でした。ありがとうございました!
穴という穴に漏れの精子を流し込んだら、鯖が発狂しちゃった。
壊しちゃってごめん。
コマンドラインだけのチャットプログラムを作って、
ネットワーク勉強したところです。
もっと、複雑な通信規則のアプリを作りたいとき、
なんの命令待ちか状態の推移の管理の仕方で、
わかりやすいサンプルプログラムや本などないでしょうか。
本屋に行ってもいい本みつからないです。
・データを送信したので、OKを待っている状態
・データを待ってる状態
どんどん何を待ってるか、変わってくると思うんです。
よろしくお願いします。
linuxからWINDOWS2000に、20000バイトの文字列送信したら
WINDOWSの方で、2回に分けてrecv()が呼ばれているようでした。
■linux
send(soc,buf,strlen(buf)); //20000バイトの文字列を送信
WINDOWSのグローバルIPアドレスを指定して送信。
ブロッキングモード
■WINDOWS
while(1){
recv(soc,buf,sizeof());
}
ブロッキングモード
//2回に分けてrecvが呼ばれました。16000文字と4000文字
サイズが大きいときは、分けてrecv関数が呼ばれることを
想定してプログラミングしないとだめでしょうか。
16000バイトというのは、環境関係なく決まった数字ですか?
FAQよむことをおすすめする。
TCPならどこで切られるか、どこでくっつくかは予想できない。
UDPで2回に分かれたというなら、バグじゃね?
UDPの場合1回で送信し切れなかったら単純に捨てられる
>>182 >>183 レスありがとうございます。
今回はTCPでした。UDPはそうでしたか。ふむふむ。
図書館で調べたら、パケット一個分だっり8000ぐらいのときもあったり
ばらばらなんですね。
ブロッキング、ノンブロッキング、ローカルホスト、リモートホスト
でも違うみたいです。
勉強になりました。
ありがとうございました。
>>184 というか、TCPはストリームベースのプロトコルだから、そういうことは
一切仮定してはならない。
TCPは、実際にはいくつかのIPパケットとして送られるデータを
区切りの無いただのバイト列のように見せる。
TCPで「メッセージの区切り」のようなものが欲しければ、自分で(アプリ層で)
仕掛けを作りこまなければダメだ。
>>185 大きなデータもらうときは、
std::string s;
s+=buf;
で、終わるまでこれを繰り返すようにして
解決できました。
勉強になりました。ありがとうございました。
std::stringって\0含むデータでもまともに動いたっけ?
内部では動く。ただしもちろん、operator+=(const char*)は引数の終端を見る。
bufに\0が含まれてると破綻するわけですね
ACEってライブラリ使ってる方居ますか?昔ここで薦められましたが
191 :
デフォルトの名無しさん:2007/04/06(金) 14:02:00
windows環境で一台の管理端末から複数の制御端末を制御する
プログラムを開発したいのですが
この場合、制御される側にサーバアプリを置くのが一般的だと思っています。
しかし、それによって制御される側にWindowsファイアフォールを
開ける必要があると思うのですが、それをしたくないとしたら
管理端末にサーバアプリを置いて、制御端末にクライアントアプリを
置けばいいと考えています。
具体的にどのように考えているかというと
@制御端末は管理端末にsendメッセージを送信したあとrecvメッセージがあるまでひたすら待ち続けます。
Aそして管理端末の操作によりrecvメッセージが返り、そのメッセージの指示に従い動作します。
の繰り返しを行うのです。
この考え方に非現実的でないとか不備がありましたら、
指摘してもらえますでしょうか?よろしくおねがいします。
問題ないでしょう
制御端末ってのは「制御される端末」って意味なのか?
変な言葉の使い方だな。
制御端末というと普通はunixの制御端末(/dev/tty, controlling terminal)のことだがな。
まああれだ
世間様の常識と自分の常識は必ず一致するとは限らないわけだな
すみません、初心者です。[ADSLモデム]-[ルータ]-[PC]と繋いでいるんですが、
ルータのWAN側グローバルIPを取得したいのですが、直接ルータに聞く方法ってありますでしょうか。
>>197 Windowsアプリのプログラムの中で取得したかったんです。
httpでルータの管理画面にアクセスして、取得すると、機種依存するんで、
何か決まった方法があるのか知りたかったんです。
直接ルータではなく、一度、外にアクセスするのが一般的なんでしょうか。
まずUPnPを試す。
GetExternalIPAddressをサポートしてなかったら機種依存するか
外部に接続する方法しかない
>>199 ありがどうこざいます。UPnPのサンプルが見付かりました。
ひとまずは、UPnP対応ルータみたいなので、これでいけそうです。
201 :
デフォルトの名無しさん:2007/04/10(火) 18:32:35
ネットワークアプリ開発の勉強をしている者でございます。
MFCのCAsyncSocketについて教えてください。
クライアントのOnSendハンドラがコールされるときって
接続直後、ネットワーク障害発生以外に
どのようなケースがあるのでしょうか?
受信側がさばききれないくらいの勢いで送信しまくって
送信バッファがいっぱいになったとき
もちろん送信バッファのサイズを仮定するプログラムを書いてはならない
(つまりいつでも呼ばれうると考えるべき)
203 :
デフォルトの名無しさん:2007/04/11(水) 09:26:49
ネットワークプログラミングできる香具師って少ないの?
知り合いの人買いが人足りないって困ってた。
まあ派遣になんて人集まらなくて当たり前と心の中で思ってたが。
どんなアプリの?
webアプリなら死ぬほど転がってると思うが
>>205 ネットワークアプリだっつってんだろ
webアプリなんざネットワークプログラミングじゃねーよ
ライブラリでACEとboost::asioとRakNet、OpenTNL、HawkNLどれがいい?
用途は?
webアプリか?
mmoかな、あと暗号認証も
暗号系はCPUパワー食うし遅延も発生するから辞めておいた方が。
ネットワークを隔離して閉網で構成した方がパフォーマンスもセキュリティも高い。
211 :
デフォルトの名無しさん:2007/04/13(金) 22:13:10
今日から勉強をはじめました。
環境はWindowsXPでVisualStudio2005です。
手始めにwinsockの初期化と終了処理ということで、
#include <winsock2.h>
int main()
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2,0), &wsaData);
WSACleanup();
return 0;
}
というプログラムを書いてみたのですが、
コンパイルする時に
error LNK2019: 未解決の外部シンボル_imp_WSACleanup@0 が関数_mainで参照されました。
error LNK2019: 未解決の外部シンボル_imp_WSAStartup@8 が関数_mainで参照されました。
というエラーが出て、いきなり躓いてしまいました。
これは、どうすればいいのでしょうか?
213 :
コッチェビ:2007/04/13(金) 22:21:52
(´・ω・`)コッチェビ・・・ws2_32.lib・・・
214 :
211:2007/04/13(金) 22:30:11
プロジェクトのプロパティのリンカ→入力→追加の依存ファイルのところでしょうか?
選択のところにws2_32.libがないのですが、これはネット上からダウンロードするのでしょうか?
自分で調べろ
#pragma comment(コッチェビ, "ws2_32.lib")
ここって初心者スレだっけか
>211
つーかエラーの原因くらい特定できるようになれよバーカwwwwwwwww
>>210 暗号は認証にしか使わないので大丈夫かなパスの平分で流すよりは自前でいじるのもなんだし
ついでだからhttpsとか汎用性があるのを使おうかとおもって
まあ三期の暇人学生が作るmmoゲー(予定)なんで使いやすいのを・・・
パスワードを平分で流したくないだけなら、
チャレンジ&レスポンスって方法もありますよ。
>>210は馬鹿だけど。
222 :
デフォルトの名無しさん:2007/04/14(土) 21:35:08
クラック版を不可能とは言えないまでも、
作成がかなり難しくすることは可能でしょうか?
また、そうするためにはどのような対策(パッカーも含めて)を行う必要があるでしょうか?
メモリ書き換え対策?の仕組みや、解読されづらいパッカーなど、あったら教えてください。
なんだ?誤爆ですか?
一ついえるのは「パッカー自作しろ」
>>221 チャレンジ&レスポンスを見てみましたが、サーバー側で独自のレスポンスを作り
比較するらしいのですがその最初にパスなどを受け取るときにはどうするかが載ってなかった・・・まいっか
電気技術者三種が8月にあるから暇じゃなくなった・・・・orz
non-blockingモードを調べていて気になったんですが、
最近みたソースで select / poll でも EAGAINまたは、EWOULDBLOCK の
チェックしてたんですが、select/poll でもerrno にこれがセットされることって
あるんですかね??マニュアルにはなかったもので。。
selectそれ自体がEAGAINで戻ってくることはないはず
228 :
226:2007/04/16(月) 21:05:35
>>227 サンクス。やっぱり無駄なチェックなんですね。。。
ちなみに、non-blockingモードでも、selectやpollで待ち合わせてから、
send/recv すれば、EAGAINは返ってこないと思ってますが、
あってますよね?
selectから抜けて、sendするまでにバッファが詰まるとかあるのかな??
全部やっとけば?
231 :
デフォルトの名無しさん:2007/04/16(月) 23:49:09
プログラムに組み込むような形のhttpサーバを探しています。
できるだけ小さいもので、良いものがあれば教えてください。
232 :
231:2007/04/17(火) 00:05:14
自分でfnordというのと、cherokeeというのを見つけました。
>>228 それ俺も怖い。
pollで書き込み可能になってwriteしたらEAGAINとか
poll->読み込み可能->readでEAGAINとか。
似たようなことをここで聞いたらソース嫁ってずーっと前にいわれた。まだ読んでない。
だから一応read/writeでもEAGAINをチェックしてる。
アトミックじゃないんだからEAGAINになる可能性はあるだろ。
MS系のAsync〜はrecvで読み込んでる最中にさらに
データが到着したら、次回のイベントは発火するけど、
データ自体は今回のrecvで帰ってくることがある(ので
次回recvしても読めないこともある)、ってMSDNあたり
で見た気がする
236 :
226:2007/04/17(火) 23:35:23
229のいう通りとりあえず全部やっておくのが安全ですね・・・。
一般的にファイアウォールのソフトウェアは
どんなモジュールをトラップしているものなのでしょうか?
(Windows)
ファイアウォールのソフトを手動で削除したら、
CScript.exeから
Msxml2.XMLHTTPオブジェクトなどのオブジェクトを使用して
インターネットにアクセスする事ができなくなってしまいました。
WinHttp.WinHttpRequestなどもすべて同じです。エラーが起きます
WScript.exeは大丈夫です
削除後、まず最初に、WScript.exeからもCScriptからも
FileSystemObjectが使えなくなっていたので
レジストリを調べたらFSOのActiveXコンポーネントscrrun.dllのパスが
ファイアウォールのDLLのパスにすり返られていたので
これは直しました
でもMsxml2.XMLHTTPやMicrosoft.XMLHTTPなどはすべて
そういう事にはなっていません。元のパスのままのようです
このような現象はどこがトラップされて起きているものなのでしょうか?
削除の仕方がまずかった訳で、再インストールしたりすれば
元に戻せるのかもしれませんが、
一応ダメ元で手動復元にトライしたいのです。
238 :
237:2007/04/18(水) 04:18:40
あ。scrrun.dllをフックしていたのは
正確にはファイアウォール部分ではないですね・・・
総合セキュリティソフトだったので・・・
スクリプトブロックの部分でした
>>236 来るはずがないんだったらチェックしたって害はないからな
APOP破られたの?
MD5 の脆弱性が表面化してきた ってことか。
前からだろw
あくまでハッシュ生成のためだけに使うべきだな。
同一ハッシュ値の生成(自動ではなく 人手の補助有り)から pass が捕まったってことだし
MD5 をハッシュ関数にするのはまずいんでねーの?
色んなデータを扱う限りは値はバラけてくれるんじゃないかなあ。
扱うデータに偏りがある場合は無理かもしれんけど。
なんか良いハッシュ関数ある?
SHA-256
250 :
デフォルトの名無しさん:2007/04/20(金) 22:42:12
受信、送信ソケットバッファを20Mbyteとってるんだけど
デカ過ぎ?
1TBくらいメモリがあるならそれくらい気にしなくていいんじゃね
100セッションで2GBか。楽しそうだな。
セッション張りまくりで速攻落とせそう。
このスレはハッカが盗り放題です><
http://www.atmarkit.co.jp/fsecurity/rensai/crypt01/crypt02.html その一方、大きな問題としてSHA-2がSHA-1の代替としてふさわしいハッシュ関数であるのかという議論がある。
というのも、昨今、MD5やSHA- 0に対する攻撃成功例が相次いでいること、
またWang氏らの攻撃によって予想よりも簡単にSHA-1への攻撃が成功したことなどから、
NISTや暗号研究者はMD5/SHA-1の設計方針自体に実は脆弱性があるのではないかと疑い始めている。
そのため、MD5/SHA-1の設計方針の延長線上で設計されているSHA-2についても
本当に安全なのか確信が持てなくなってきているのが現状である。
2005年10月に行われたハッシュ関数に関するワークショップ(NIST Cryptographic hash workshop)の席上でも、
NIST自身が今後10年間でSHA-256に対する攻撃方法が見つかる可能性はあると考えていると述べている。
さらに、AESの選定と同じように、新しいハッシュ関数選定のための公募を実施すべきとの意見も根強く残っており、
2006年8月には再度ワークショップが開催されることが決まった。
ここでの議論次第では数年後にハッシュ関数コンテストの実施もあり得る。
近年国際的にもハッシュ関数の設計に関する研究が活発化しており、
暗号学会でもしばらくの間、ハッシュ関数の提案や解読が続くものと考えられている。
もお2006年8月は過ぎたわけだがどうだったの?
自分で探したらこうだった
・2007年にThird Hash Function Workshop 2007を開催
・2008年〜2012年までのタイムスケジュールの提示
・2012年に新しい標準ハッシュ関数を決定する
ずいぶん気の長い話だな
5年以内にSHA-256が破られたらジエンドというわけか
いや、別に他でも作っていいわけだから。
これまでもあったように、バリアントを作ったり。
259 :
デフォルトの名無しさん:2007/04/21(土) 13:37:48
260 :
デフォルトの名無しさん:2007/04/21(土) 13:44:16
書き忘れたが、setsockoptで20Mを要求するプロセスは3つだけで
他にデカいソケットバッファを要求するプロセスはない
使用可能なメモリはどれくらいあるんだよ
262 :
一日駅長:2007/04/21(土) 13:58:46
こんにちは一日駅長と申します。
いきなりですが、PHPで作りたいものがあるんですが、
WINDOWS XPを使ってるのでAPACHE(←スペル合ってる?)をダウンロードしよ
うと思ったのですが。インストール後APACHE MONITOR IS ALREADY STRATEDとエラーが、、
なんか上手くいかんのです。全てのプログラム→からクリックしてもなにも出来ない
し、ためしにXAMPPをダウンロードしたのが影響してるのかな?????
上のを削除しようとしてもXAMPPが既に起動してますと表示されます。起動してないつもりだけど(涙)
スレ違いならスマソ。初心者で用語とか全くチンプンカンプンなので分かり易く
説明キボン。
スレ違い
264 :
一日駅長:2007/04/21(土) 14:02:36
どこにいけば、、、、
webプログラミング板ってのがあったと思う
>こんにちは一日駅長と申します。
こんにちは。シュールな書き出しですね。
268 :
デフォルトの名無しさん:2007/04/22(日) 09:27:00
269 :
デフォルトの名無しさん:2007/04/22(日) 09:55:10
沖縄県の方へ(命に関わる注意事項です)
沖縄県での選挙ですが、どうか民主党だけは避けてください。県民の生命に関わる可能性があります。
民主党の最大の公約は一国二制度(※)ですが、一度「一国二制度 沖縄 三千万」等で検索をお願いします。
この際、民主党のHPで調べても良いです。以下の注釈↓と矛盾することは書いてないはずですから…
※一国二制度
簡単に言えば沖縄を中国と日本の共有物にし、そこに3000万人の中国人を入植させます。
(つまり沖縄人口の 96% を中国人にして、実質、沖縄を中国人の居住地とします。)
さらに「自主」の名の下、沖縄で有事が起きても自衛隊は干渉できません。
3000万人の中国人が、少数派となった130万人の日本人に何をしても、です。
そして反日教育を受けた中国人の反日感情の強さは、ほとんどの日本人の理解を超えるものです。
今回の選挙で民主党が勝った場合、「自主」「発展」を連呼しつつ段階的に進めていくことになります。
自主と言っても、自主を認めるのが「住人の96%が中国人となった」後だということに気をつけてください。
発展と言っても、新沖縄の少数派となった「少数民族日本人」の発展ではないことに気をつけてください。
>>258 暗号の専門家が手がけてないオレオレハッシュのほうがよっぽど危険じゃね?
オレオレハッシュを暗号の専門家が作ったらいいのでは。
専門家達のチェックを通ったらオレオレじゃないわけだが
オレたちが暗号の専門家になればいい
たぶん専門家を雇った方が効率いい
つーかまだ破られたわけじゃないんだからSHA-256使ってればいいだろ
専門家が作ったぐらいでは、信頼できないわけだが。
専門家もピンキリ。
自称専門家なんてのも居るし。
windowsどうしのTCPです。
2つときは、簡単だったのですが、A,B,Cと3つパソコンでやまびこ
みたいにエコーをしたいと思ってます。A→B→C→B→A
子スレッドがそれぞれ担当するとします。
--@Aの子スレッドのプログラム--
send(); //A→Bのメッセージを送信
recv(); //B→Aのメッセージを受信
--ABの子スレッドのプログラム--
recv(); //A→Bのメッセージを受信
B⇔Cのための子子スレッドを呼び出し?
send(); //B→Cのメッセージを送信
--BBのB⇔Cのための子子スレッド--
send(); //B→Cのメッセージを送信
recv(); //C→Bのメッセージを受信
こういう感じでしょうか?
疑問がありまして、Bの子スレッドのなかで、Bを呼び出して子子スレッドは、
たぶんダメですよね。実際に実装するときは、どのようになるでしょうか。
よろしくお願いします。
279 :
278:2007/04/23(月) 00:34:05
訂正すみませんです。
よろしくお願いします。
--@Aの子スレッドのプログラム--
send(); //A→Bのメッセージを送信
//Cから戻ってくるまで、ちょっと待ちます
recv(); //B→Aのメッセージを受信
--ABの子スレッドのプログラム--
recv(); //A→Bのメッセージを受信
B⇔Cのための子子スレッドを呼び出し?
//Cからメッセージが来てsend()
send(); //B→Aのメッセージを送信
--BBのB⇔Cのための子子スレッド--
send(); //B→Cのメッセージを送信
recv(); //C→Bのメッセージを受信
作成者、送信元、送信先
と言うような情報をパケットに持たせて、
プログラム側はその情報に従ってメッセージを送信し、
作成者まで戻ってきたら破棄する。
という感じ?よく分からんけど
281 :
278:2007/04/23(月) 01:59:09
>>280 レスありがとうございます。そういう理論ですか。なるほどです。
ネットワークプログラミングとマルチスレッドが、
初心者なので、実際のプログラミングでどうしたら、
良いのかと思いまして。
Bのプログラミングは、もうちょっと細かく見ると
WSAStartup()->socket()->bind()->listen()->accept()->recv()->
B⇔Cのための子子スレッドを呼び出し?
->send()->closesocket()->WSACleanup()
■子スレッドで、_beginthread使っても良いなら、わかりやすくできるんですが、
だめなんですよね?
■WSAStartup()->socket()->bind()->listen()->accept()->recv()->
{B⇔Cの処理 WSAStartup()->socket()->connect()->send()->recv()->WSACleanup()}
->send()->closesocket()->WSACleanup()
スレッド使わないで、WSAStartup()2回呼んだら、どうなるんだろうとか、
一回目のWSACleanup()で、A⇔B,B⇔C、両方の接続切れちゃったりしますよね。
とか、いろいろ疑問で。実験して見ようと思うんですが、頭がごちゃごちゃして
難しいです。
■あとは、はじめからBのプログラミングで、
AがBに接続をして、アクセプトした瞬間に、その親スレッドで、
A⇔B,B⇔Cのやり取りするスレッドを、立ち上げてスレッド間のメッセージで
タイミングをはかる方法があるかもしれないですが、スレッド間のやりとりって、
やったときなくて、難しいです。
うまく説明できず、すみません。的外れなこと言ってるかもしれないです。
2番目と3番目の■について、ここに気をつけるなど、アドバイスいただけないでしょうか。
よろしくお願いします。
282 :
278:2007/04/23(月) 04:08:28
>>281 2番目の■実験してみました。ちょっと違うんですが、
http://www.geekpage.jp/programming/winsock/http-client.php こちらのページのプログラムを参考に、させていただき実験してみました。
int main2(int argc, char *argv[]);関数を作成しました。
内容は、
//WSADATA wsaData;
// if (WSAStartup(MAKEWORD(2,0), &wsaData) != 0) {
// printf("WSAStartup failed\n");
// return 1;
// }
// WSACleanup();
●WSAStartup()とWSACleanup()は、一回でいいと思い
にコメントを入れました。この理解合ってますでしょうか?
main()関数の中のsocketclose();のあとに
main2(argc,argv);を呼び出しました。
●すると、同じページが2回表示されました。
この要領で、281も実装すれば大丈夫でしょうか?
283 :
278:2007/04/23(月) 04:16:18
あっ、でもクライアントプログラムでした。
■WSAStartup()->socket()->bind()->listen()->accept()->recv()->
{B⇔Cの処理 socket()->connect()->send()->recv()}
->send()->closesocket()->WSACleanup()
だと、サーバプログラムで、上記のように実験しないとだめですか。
んー、これで動きそうですが、状況作るの難しいです。
眠いので、もうだめです。><
プロセス間通信もここでいいんでしょうか?
親プロセスと子プロセスで、1対1のプロセス間通信をしたいです。
状態やエラーも返したいので名前付きパイプにしたいと思います。
しかし、親子が複数作られる場合があり、
当然、パイプの名前をユニークな名前にしなければならないのですが、
Windowハンドルを使えばいいでしょうか?
こういう場合、普通はどんな風にプロセス間通信しますか?
C言語にてCGIを作成しています。
作成したCGIプログラムをHTTPで確認しようとすると
「Script Execution Failed」というエラーが表示されてしまいます。
色々調べたところサーバ側ではRedhat7.1という環境でサーバを動作
させており、Linuxで作成したexeファイルしか動作できないようなのです。
(Linux使ってないのでこの辺り大分自信が無いのですが)
これはつまり、VisualC++6.0等のWindows上で動作するコンパイラで作成した
cgiファイルは使えないという事なのでしょうか?
>>284 無名パイプを継承可能で作成してさらにCreateProcessでハンドルを継承可能にする。
288 :
285:2007/04/23(月) 18:35:48
>>286 SHOCKだ!LINUX使いの人じゃないとCGI作れないんですね。
返答ありがとうございました。
289 :
284:2007/04/23(月) 18:37:13
>>288 ソースコードをLinuxマシンに転送してLinuxマシン上でコンパイルすれ
ばいい。
同じインテルだろうからアセンブラで組めばおk。
ファイルを転送するプログラムを作っているんですが、
sendに一度に渡すデータサイズはどれぐらいが適正なんでしょうか?
大きめに渡したほうが速く送れると、
どこかで読んだので大きめにしたほうがいいのかと
1MBまでなら渡しても正常に送ってくれるので
今のところ1MBにしています・・・でも、これはさすがに大きすぎるような気がして不安です。
OSがサポートする実行ファイルの形式が異なるので
WindowsとLinuxの両者でネイティブ動作する実行ファイルを作るのは不可能。
一般にコンパイル環境と異なるターゲット環境のための実行ファイルを
生成したい場合には、クロスコンパイラというものを使う。
wineつかえばいいのに
4096byte以上はフラグメントされます。
リングバッファ処理を覚えましょう。
EDITのウィンドウの文字の大きさを小さくしたいのですが、可能なのでしょうか?
文字?
CreateWindow(TEXT("EDIT") , TEXT("最初の文字") , WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT,
248 , 40 , 45 , 22 , hwnd , (HMENU)0 , ((LPCREATESTRUCT)(lp))->hInstance , NULL);
これで表示される“最初の文字”のフォントのサイズを小さくすることは出来るのでしょうか?
あと、SendMessage(hEdit, ES_READONLY, 0, 0);みたいな感じで、
目的のエディットコントロールを読み専用に変えたいのですが、↑のだと上手くいきません。
どうすればいいのでしょうか?
>>301 ごめんなさい、スレを間違えてました。本当の質問は、
n = connect(sock, (struct sockaddr *)&server, sizeof(server));
while(n==SOCKET_ERROR){
n = connect(sock, (struct sockaddr *)&server, sizeof(server));
}
という感じで、サーバに接続するようにしているのですが、どうしても上手くいかない場合があります。
というのは、サーバー側でacceptする数の上限が5個にしている場合、
6人目はconnectを素通りしているような動作をします。
6人目にこのループを抜けてもらったら困るのです。
下の方の処理で、if(n!=SOCKET_ERROR){}のようにして6人目を村八分にしようとしても、
どうやら6人目のnにSOCKET_ERRORが入ってないようで、処理から除外することが出来ません。
どうすればいいのでしょうか?
待ち行列にでも入れて、5人以下なら待ち行列から銜えれば良いのでは?
ネットワークというよりアルゴリズム的な話だと思う。
304 :
292:2007/04/25(水) 17:10:52
(´・ω・`)
チャットがしたいならIRCがあるじゃない
といったらみもふたもないな。
>>302 サーバ側はどういう挙動にしてますか?
5クライアントをaccept()した後にもlisten()しているとか?
コネクションバックログ、という、
サーバがacceptを呼ぶ以前にOS側で接続を
成立させておく機能があるわけ
C言語にてCGIを作成しています。
ローカルのプログラムからサーバーにあるCGIを起動する際に引数を
渡してやりたいのですが上手くいきません。
ローカル側のアプリから以下のようにして引数の文字列「data」をCGIに渡してます。
hRequest = HttpOpenRequest(
hHttpSession,
"GET",
"test.cgi?data",//「data」という文字列をCGIに渡す
NULL, NULL, NULL, 0, 0);
CGI側のプログラムは以下のようになっています。
int main(){
char szBuf[256];
int i;
char c;
for (i = 0; (i < 255) && (c = getchar()) != EOF; i++) {
szBuf[i] = c;//引数として与えられた文字列を標準入出力から取得
}
szBuf[i] = '\0';
printf("Content-type:text/html\n\n");
printf(szBuf);//引数の文字列を描画
printf("test");//Test用
return 0;
}
CGIを実行してみると「test」というテスト用に書き出した文字列は吐き出されるのですが、
肝心の引数として与えた文字列が書き出されません。
ローカルでの引数の渡し方か、CGI側での引数の取得方法のどちらかが
間違ってると思うのですが、どなたかアドバイスして頂けないでしょうか?
>>308 GETとPOSTで受信方法が違う。GETの場合は環境変数のQUERY_STRINGから読み取る。
POSTの方がいいよ
311 :
308 :2007/04/26(木) 07:57:43
>>309 ありがとうございます!ようやく引数を取得する事が出来ました!!
本当に困ってたんです。適切なアドバイスありがとうございました!
POSTの方がいいよ
WSAAsyncSelect(sock[i], hwnd, WM_MYMSG2, FD_ACCEPT);
MessageBox(hwnd, "OK", "OK", MB_OK);
sock[i] = accept(sock0, (struct sockaddr *)&client_s, &len_s);
↑のプログラムなんですが、クライアント側から接続要求がないのに
WSAAsyncSelectで待機せずに素通りしてしまいます。どうしてでしょうか?
ちなみにWM_MYMSG2では何も処理をしてません・・・
たぶんWinsockの基本を勉強しなおした方がいいと思うよ
>>313 どうしてWSAAsyncSelect()が待機するなんて思うんですか?
質問です。
WinsockでIPv6のUDPパケットを出すプログラムを書いています。
パケットの送信元アドレスをパケットを出す前に取得するにはどうすればよいのでしょうか?
パケットを出すPCは複数のIPv6アドレスを持つ可能性があるので、
送信元アドレスはできればシステムに決めさせたいのです。
IPv4では次のようなコードでうまくいったのですが、
IPv6では送信元が[::]となってしまいます。(擬似コードですいません。)
s = socket( UDP ) ;
connect( s, "remote_sockaddr" ) ;
getsockname( s, src_sockaddr ) ;
getnameinfo( src_sockaddr, &src_addr_string, &src_port_string ) ;
>>314-315 ちょっと勉強しなおしました。
別に待機はしないんですね。
WSAAsyncSelect(sock, hwnd, WM_MYMSG, FD_READ);で、
ウィンドウプロシージャの方でFD_READを捕まえてrecvをしようとしているのですが、
なぜかメッセージが送られてきてもWM_MYMSGがプロシージャに送られて来ません。
原因として何が考えれれるでしょうか?
ほんとにチョットだけだな。
>>317 > なぜかメッセージが送られてきてもWM_MYMSGがプロシージャに送られて来ません。
言ってる意味がわからん。何のメッセージが送らてきたんだ。WM_MYMSG
のメッセージが送られてきたのではないの?
言ってる意味が分からないのはたぶん言ってる本人が理解してないからだよ。
>>317 「もっと勉強し直せ」としか答えようがない
ちゃんとした質問が書ける時点で大方自己解決してしまうことが多いのだが
それならそれでいい。
「自己解決しました」だけで去っていくのは最悪だが
>>319 クライアントからメッセージを送っても、プロシージャにWM_MYMSGが送られてこないということです
だから何のメッセージを送ったんだよ
日本語は理解できるか?
メ・・・メッセージ・・・で・・・す・・・ これが・・・せい・・・いっぱい・・・です
受け取って・・・ください・・・ 伝わって・・・・・・ ください・・・
>>323 1つずつ処理を追いかけていけば怪しい部分が分かると思うけどな
>>324 char型のメッセージです。"Hello"って文字列です。
メッセージが送られてきたときだけrecv()を呼び出したいので・・・
とあるスレから誘導されて参りました。
以下コピペですが、どうかお願いいたします。
C、C++、Javaを用いて、ネットに存在する情報を取得したいのですが、可能でしょうか?
使用目的は、 「株式の時系列データを取得し、株式の解析に用いる」 です。
例えば、プログラムを実行すると、
http://table.yahoo.co.jp/t?s=5010.t&g=d 上記ページの、
2/16〜4/27までの始値、高値、安値、終値を取得する。
そして、それらを数値として変換し、解析に用いたいのです。
研究室の条件により、C、C++、Javaのみでプログラムを作成しなければなりません。
可能でしたら、参考になるWEBサイトを教えていただければ幸いです。
よろしくお願いいたします。
HTTP通信と構文解析じゃね?
おれも株の自動化してみたいなーFXとかほかのもやる予定?
Javaでいいじゃん。遅くったって関係ないし
仕事ならともかく学校のならJavaで1日で作れ。
>>329 ありがとうございました。
HTTP通信と構文解析ですか…。あとで調べてみます。
FXとかですが、自分なりに理論が固まれば取り組もうと思ってます。
>>332 おー!ありがとうございます!
Javaで組めるようにならないといけないですね…。
そのスレを参考にして作り上げたいと思います。
>327
コネクション成立処理がくさそうな気がする。
>>333 javaは読めればいいわけで、重要なのは理解できるかだと思うよ
理解できればCにもできるし、まあ大学の研究室なら公開してくれwww待ってる
>>327 「ソケット上で文字列を送っても WM_MYMSG の処理に行かない」ってこ
とね。コードを見ない限り、もう「ちゃんとコードを組めばできるはず」
としかい言いようがない。
promisc
>>338 あなたが神か。
インターフェースの設定を以下のコマンドで変更したら、
teherealに関わらず、マルチキャスト受信できました。
ifconfig eth0 promisc
また、以下の設定でもマルチキャスト受信できるようになりました。
ifconfig eth0 allmulti
蛇足ですが、
「ifconfig eth0 -multicast」によって、MULTICAST属性(?)を消しても、
マルチキャスト受信ができました。このあたりは、よく分かっていません。
不明な部分もありますが、当初の予定の
マルチキャスト受信できるようになりました。
ありがとうございます。
340 :
サービス定義済みポートだと返ってこない:2007/05/04(金) 07:09:13
SMTP/POP3のメールサーバを作りたいのですが、
サービスが定義されているポートだとrecv,WSARecv,send,WSASendの関数呼び出しが返ってきません。
サービスが定義されていない24や27015だとちゃんと送信、受信がすぐに行われ関数呼び出しは返ってきます。
サービスが定義されているポートだと何か特別な処理が必要なのでしょうか?
流れとしては単純にサーバもクライアントもブロッキングモードで、ホストはlocalhost:25で
サーバはWSASocket,bind,listen,WSAAccept,recv/WSARecvとやってrecv/WSARecvで返ってこなくなります。
クライアントはWSASocket,connect,send/WSASendとやってsend/WSASendで返ってこなくなります。
ご教授のほどよろしくお願いします。
341 :
サービス定義済みポートだと返ってこない:2007/05/04(金) 08:22:44
シンプルに書いてみるとクライアント側のsendは処理が返ってくるようになりました。
でもサーバの方はWSAAcceptまではするのですが、recvで処理が返ってこなくなります。
行の節約のためエラー処理を抜きにして試したプログラムを記載します。
起動の順番はサーバ、クライアントとしてクライアントがメッセージをサーバに送り
サーバがメッセージを受け取る単純な形です。
見にくいかもしれませんがよろしくお願いします。
342 :
サービス定義済みポートだと返ってこない:2007/05/04(金) 08:23:50
クライアント側(コンソールアプリケーションmain)
WSADATA sWSAData;
addrinfo sHints, *pInfo = NULL;
char* pszMsg = "Helo localhost \r\n";
::memset(&sHints, 0, sizeof(sHints));
::WSAStartup(MAKEWORD(2, 2), &sWSAData);
SOCKET s = ::WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
sHints.ai_family = AF_INET;
sHints.ai_socktype = SOCK_STREAM;
sHints.ai_protocol = IPPROTO_TCP;
::getaddrinfo("localhost", "25", &sHints, &pInfo);
::connect(s, pInfo->ai_addr, pInfo->ai_addrlen);
::send(s, pszMsg, ::strlen(pszMsg), 0);
::printf("Send Msg[%s]", pszMsg);
::freeaddrinfo(pInfo);
::WSACleanup();
getchar();
343 :
サービス定義済みポートだと返ってこない:2007/05/04(金) 08:24:55
サーバ側(コンソールアプリケーションmain)
WSADATA sWSAData;
addrinfo sHints, *pInfo = NULL;
SOCKADDR_IN sClientInfo;
DWORD ulNumofRecv = 0, ulFlag = 0;
int iRet;
char achBuffer[1024];
int iSize = sizeof(sClientInfo);
::memset(&sHints, 0, sizeof(sHints));
::memset(&sClientInfo, 0, sizeof(sClientInfo));
::memset(achBuffer, 0, 1024);
::WSAStartup(MAKEWORD(2, 2), &sWSAData);
SOCKET s = ::WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
sHints.ai_family = AF_INET;
sHints.ai_socktype = SOCK_STREAM;
sHints.ai_protocol = IPPROTO_TCP;
::getaddrinfo("localhost", "25", &sHints, &pInfo);
::bind(s, pInfo->ai_addr, pInfo->ai_addrlen);
::listen(s, 1);
SOCKET a = ::WSAAccept(s, (sockaddr*)&sClientInfo, &iSize, NULL, NULL);
::printf("WSAAccept complete\r\n");
iRet = ::recv(a, achBuffer, 1024, ulFlag); //ここで処理が返ってこなくなる
::printf("recv msg[%s]", achBuffer);
::freeaddrinfo(pInfo);
::WSACleanup();
getchar();
344 :
サービス定義済みポートだと返ってこない:2007/05/04(金) 09:14:43
数分経過してからサーバがQUIT\r\nをrecvで受信しました(クライアントはQUIT\r\nは送っていない)。
何かヒントになるでしょうか。
>>344 SMTPのコマンドか?
サーバーとクライアントって、どこと接続しているのか、netstat -anoとかで確かめてみた?
>>343 send()した直後にWSACleanup()したら、送られないんじゃない?
347 :
サービス定義済みポートだと返ってこない:2007/05/04(金) 09:44:41
空いているポート(20000)でサーバとクライアントを起動したら
netstat -anoの結果はTCP 127.0.0.1:20000でSTATEがLISTENINGとESTABLISHEDの2つが出ました。
サーバとクライアントでちゃんと通信が確立しているみたいです。
しかしSMPTポート(25)で行ったら127.0.0.1:20000は表示されなくなりました。
bind,listen,acceptもconnectも成功しているのに何故表示されないのでしょうか。
よろしくお願いします。
348 :
サービス定義済みポートだと返ってこない:2007/05/04(金) 09:47:02
すいません。347に嘘を書いてしまいました。
SMTPポート(25)で行ったところさっきの空いているポート(20000)と
同様に127.0.0.1:25のLISTENINGとESTABLISHEDが表示されています。
プロセスID?(PID)も同じです。
通信は確立していると見てよいのでしょうか。
何故recvできないのでしょうか?
よろしくお願いします。
349 :
サービス定義済みポートだと返ってこない:2007/05/04(金) 09:53:13
ちょっと気になることがありますので追記します。
netstat -anoの結果で
Proto Local Address Foreign Address State PID
(1)TCP 127.0.0.1:25 0.0.0.0:0 LISTENING 5208
(2)TCP 127.0.0.1:25 127.0.0.1:3744 ESTABLISHED 5208
のあとに
(3)TCP 127.0.0.1:3744 127.0.0.1:25 ESTABLISHED 3868
という(2)のForeign Addressが(3)のLocal Addressで使われていました。
PIDも異なります。
空いているポート(20000)では(3)のような重複したものはありませんでした。
もしかしたら、別のプロセスへメッセージが送られているのでしょうか?
よろしくお願いします。
>>349 心配なら自分のサーバプログラムとクライアントプログラムでPIDを表
示してみれば?
(1)がサーバのWSASocket(),bind(),listen(),WSAAccept()のパラメータ のソケット
(2)がサーバのWSAAccept()の結果、recv() のソケット
(3)がクライアントのソケット
でしょう。
>>349 一応だけど、ファイアウォールの設定とログも確認して。
352 :
サービス定義済みポートだと返ってこない:2007/05/04(金) 10:07:20
PIDが3868のものをタスクマネージャで調べてみたらCCAPP.EXEでした。
NortoAntiVirusのアプリケーションみたいです。
それで調べてみたら電子メールのスキャンを無効にするとうまく動くようになりました。
345さんありがとうございました。
346さんもありがとうございました。
それにしてもノートンには困ったものです。
353 :
サービス定義済みポートだと返ってこない:2007/05/04(金) 10:09:38
350さん、351さんもアドバイスありがとうございました。
354 :
サービス定義済みポートだと返ってこない:2007/05/04(金) 10:12:42
>350さん
あれ、確かにサーバとクライアントはプロセスが違うはずですよね。
でも同じPIDでLISTENINGとESTABLISHEDになっています。
他に127.0.0.1:25はないようだし。
謎ですね。
もう分かったから
返ってこなくていい
356 :
サービス定義済みポートだと返ってこない:2007/05/04(金) 10:19:59
サーバ側のPIDでLISTENINGとESTABLISHEDが表示されるみたいです。
クライアント側のESTABLISHEDがあってもいいようなものですが、どうなのでしょうか。
ちょっと気になりますね。
Nortonを悪者にしようとするのはイクナイ
358 :
非ブロッキングモードでAcceptしたら:2007/05/05(土) 13:11:12
お世話になります。
またまた、よくわからないことができたのでご教授願います。
非ブロッキングモードでlisten中、WSAAcceptにより新しいソケットを作ったのですが、
デフォルトで非ブロッキングモードのような動作をWSARecvでします。
ブロックせずにWSAEWOULDBLOCK(10035)を返してくるです。
おまけにioctlsocketのFIONBIOで0(ブロッキングモードに変更)を指定すると
WSAEINVAL(10022)を返して失敗します。
非ブロッキングモードのlistenソケットによりacceptされてできたソケットはずっと
非ブロッキングモードで動作するしかないのでしょうか。
よろしくお願いします。
359 :
非ブロッキングモードでAcceptしたら:2007/05/05(土) 13:13:47
これがテストコードです。見にくくてすみません。コンソールアプリケーションのmainのコードです。
WSADATA sWSAData;
WSAEVENT hEvent;
addrinfo sHints, *pInfo = NULL;
SOCKADDR_IN sClientInfo;
DWORD ulNumofRecv = 0, ulFlag = 0;
WSABUF sBuffer;
int iRet;
char achBuffer[1024];
int iSize = sizeof(sClientInfo);
::memset(&sHints, 0, sizeof(sHints));
::memset(&sClientInfo, 0, sizeof(sClientInfo));
::memset(achBuffer, 0, 1024);
::WSAStartup(MAKEWORD(2, 2), &sWSAData);
SOCKET s = ::WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
sHints.ai_family = AF_INET;
sHints.ai_socktype = SOCK_STREAM;
sHints.ai_protocol = IPPROTO_TCP;
::getaddrinfo("localhost", "25", &sHints, &pInfo);
::bind(s, pInfo->ai_addr, pInfo->ai_addrlen);
::listen(s, 1);
hEvent = ::WSACreateEvent();
::WSAEventSelect(s, hEvent, FD_ACCEPT);
::WSAWaitForMultipleEvents(1, &hEvent, FALSE, WSA_INFINITE, FALSE);
長いので次に続きます。
360 :
非ブロッキングモードでAcceptしたら:2007/05/05(土) 13:16:25
SOCKET a = ::WSAAccept(s, (sockaddr*)&sClientInfo, &iSize, NULL, NULL);
sBuffer.buf = achBuffer;
sBuffer.len = 1024;
u_long ulMode = 0;
iRet = ::ioctlsocket(a, FIONBIO, &ulMode);
if (iRet == SOCKET_ERROR) {
int iError = ::WSAGetLastError();
::printf("::ioctlsocket Error code is %d", iError);
}
iRet = ::WSARecv(a, &sBuffer, 1, &ulNumofRecv, &ulFlag, NULL, NULL);
if (iRet == SOCKET_ERROR) {
int iError = ::WSAGetLastError();
::printf("::WSARecv Error code is %d", iError);
}
else
{
::printf("recv msg[%s]", achBuffer);
}
::freeaddrinfo(pInfo);
::WSACleanup();
getchar();
以上です。長いですが、listen用のソケットsを作成listenし、WSAEventSelectで非同期モードにしイベントシグナルを待ってからWSAAccept、WSARecvするかんじです。
何か単純なミスがあるのかもしれません。よろしくお願いします。
361 :
非ブロッキングモードでAcceptしたら:2007/05/05(土) 13:45:01
ちなみにクライアントはTera Termでlocalhost:25で接続しました。
MSDNをみるに、
ioctlsocket:
>To set the socket back to blocking mode, an application must first
>disable WSAAsyncSelect by calling WSAAsyncSelect with the lEvent
> parameter equal to zero, or disable WSAEventSelect by calling
>WSAEventSelect with the lNetworkEvents parameter equal to zero.
WSAAccept:
> The newly created socket has the same properties as socket s including
>asynchronous events registered with WSAAsyncSelect or with WSAEventSelect.
だからだな。
363 :
非ブロッキングモードでAcceptしたら:2007/05/05(土) 14:01:42
>362さん
ありがとうございます。
WSAEventSelectなどの設定を引き継いでしまうんですね。
さっきのテストコードのWSAAcceptの呼び出しの直後に次のコードを追加し、
WSAEventSelectを別のイベントを使って無効にしたら行けました。
WSAEVENT hEvent2 = ::WSACreateEvent();
iRet = ::WSAEventSelect(a, hEvent2, 0);
if (iRet == SOCKET_ERROR)
{
int iError;
iError = ::WSAGetLastError();
::printf("::WSAEventSelect Error code is %d", iError);
}
WinSockは難しいですね。でもちゃんとMSDNを読まなかったのが、というか英語だから僕には無理っぽいですが、それがまずかったですね。
ありがとうございました。
ただ、一つ疑問が残ります。WSAEventSelectの設定をacceptしたソケットが引き継ぐのはわかったのですが、
内部で勝手にWSACreateEvent()でイベントを作成して、それでWSAEventSelect(a, 内部で勝手に作ったイベント, 引き継ぐイベントフラグ)
というような呼び出しをしているのでしょうか。
もしそうなら、そのイベントをできればこっちで知りたいし、破棄したりもしたいのですが。
MSDNを見てみます。でも僕だけだと本当に心もとないのでご支援お願いします。
364 :
非ブロッキングモードでAcceptしたら:2007/05/05(土) 14:11:02
The WSAEventSelect function automatically sets socket s to
nonblocking mode, regardless of the value of lNetworkEvents.
To set socket s back to blocking mode, it is first necessary
to clear the event record associated with socket s via a call
to WSAEventSelect with lNetworkEvents set to zero and the
hEventObject parameter set to NULL. You can then call ioctlsocket
or WSAIoctl to set the socket back to blocking mode.
WSAEventSelectにこんなことが書いてありました。
hEventObjectはNULLでかまわないみたいなのでさっきの修正コードのhEvent2はなしにして
iRet = ::WSAEventSelect(a, NULL, 0);
これだけで行けました。
でも内部で勝手に作っているかもしれないWSAEVENTについては謎です。
365 :
非ブロッキングモードでAcceptしたら:2007/05/05(土) 14:27:44
The socket created when the accept function is called has the
same properties as the listening socket used to accept it.
Any WSAEventSelect association and network events selection set
for the listening socket apply to the accepted socket. For example,
if a listening socket has WSAEventSelect association of hEventObject
with FD_ACCEPT, FD_READ, and FD_WRITE, then any socket accepted on that listening socket will also have
FD_ACCEPT, FD_READ, and FD_WRITE network events associated with the same hEventObject.
If a different hEventObject or network events are desired,
the application should call WSAEventSelect,
passing the accepted socket and the desired new information.
このevents associated with the same hEventObjectというようにlistenのソケットと同じイベントに
結び付けられるみたいです。
つまり内部で新しいWSAEVENTが作られているのではなく、acceptするソケットが関連付けているイベント
に対して新たなソケットも関連づけられるようです。
なのでさっきのように::WSAEventSelect(a, NULL, 0);とすればacceptで新しく作られたソケットの関連付けは
とけることになるみたいです。
ご支援ありがとうございました。
もういいから二度と来ないでくれ
winsockのメッセージ型の非同期ソケットって昨今のブロードバンドだと
メッセージだらけになって追いつかなくなりそうじゃないですか?
32KBのバッファを仮定するなら、10MB/sの転送には、
約300回/sくらいメッセージが来ることになるね。
かちゅはメッセージ型の非同期ソケット使ってるけど
高速回線だとスレッドを取得し終えるまで操作できなくなってたな
受信してからの処理に時間がかかってるんじゃねーの。
うんにゃ、キューに非同期ソケットのメッセージが詰まって
入力メッセージを処理できなくなるから。
WindowsはPostMessageでポストしたメッセージのほうがキーボードやマウスからの
入力メッセージより優先度が高いという仕様なので。
Janeもそうだよ
でもJaneでストレスを感じたことはない
一般的に、普通に受信するだけなら
ウィンドウが操作出来なくなるなんて事は無い。
普通は、一回のFD_READで4K-8K程度は受信できる(たぶんsockopt次第)。
で、何故操作出来なくなるかというと
(recvのバッファが小さいという可能性もあるが)
recvのハンドラ内で重い処理をしているからと思われる。
具体的には、毎回ディスクに書き込みをするような作りだと
「ウィンドウが動かせない」状態になる。
gzipの展開程度は、重い処理には入らないし
実際の画面描画はWM_PAINTで行われるので
これも「ハンドラ内の重い処理」にはならないはず。
かちゅはそんな作りになってないけど。
受信したばかりのスレッドが保存されていないという「バグ」が報告されるくらいだし。
かちゅの場合IEコンポへの書き込みがボトルネックになってるかも
再描画メッセージがキューの中で後回しにされるからじゃない?
Mozillaは入出力メッセージをある程度優先して処理するような小細工が入れてある
recvの中でIEに書き込みしてそれが待たされてる。
ってか非同期IOつかってんでないの?
OnRecvがウインドウメッセージ経由で駆動され、
変換処理、IEへの書き込み処理をその中でしている以上、
それらの処理が終わるまで他のウインドウメッセージが
処理されるわけがない。
>>382 nsWindow::OnKeyDownあたりの処理ですか?
長くてよくわかりません。
サーバー型のチャットをCでやってます。
接続の最大人数を5人までにしたくて、5人と接続をしたら、
誰か一人接続を終了するまでacceptをしないように設計しています。
ここからが問題なのですが(クライアント側の問題です)、
6人目がconnect()すると、特にSOCKET_ERRORも返さず、
その後そのソケットにsend()を行っても特にエラーを返しません。
これはどういう状況なのでしょうか?
(サーバーのログを見ると、6人目とは接続を行っていないので
当然6人目からのメッセージは受信してません)
>>384 accept してからスレッドに処理を任せて再度 accept
するまでの間に到着した connect 要求は次の accept
で処理されるように待たされることになる(listen の
第二引数の説明参照)。
ということでその 6 人目はシステム的には「サーバー
が忙しくて accept が遅れている(ように見える)」状
態にある。
>>385 しかし、acceptが遅れているように見える状態であるなら
タイムアウトになるまでconnect()で待ったりしないのでしょうか?
用語の質問で申し訳ないのですが、
「非同期ソケット」の一般的な定義を知りたいです。
fcntl(sock_fd,F_SETFD,O_NONBLOCK);
として設定したソケット(sock_fd)は、
「非同期ソケット」と呼ばれているのでしょうか?
>>387 非ブロッキングなだけで非同期とは呼ばないな
非同期=コールバックして通知する
みたいなイメージがある
>>387 非同期=要求と応答を同時に処理しない。
普通は非同期I/O APIを使うソケットのことをいうと思う。> 非同期ソケット
POSIXだとaio_read()など。
>>388 応答をコールバックでパッシブに処理するか、
アクティブに受け取ろうとするかは、別の分類になる。
390 :
Nortonがあると通信できないのは何故:2007/05/09(水) 14:58:58
また、お世話になります。
>>343で書いたソースがサーバでクライアントはTeraTermでやってます。
netstat -anoで調べた状態で関連するものだけをピックアップすると以下の3つがあります。
TCP 127.0.0.1:25 0.0.0.0:0 LISTENING 3896(サーバ)
TCP 127.0.0.1:25 127.0.0.1:4766 ESTABLISHED 3896(サーバ)
TCP 127.0.0.1:4766 127.0.0.1:25 ESTABLISHED 3992(Norton)
以前はNortonのメールスキャン機能を停止して解決だったのですが、
どうも他のメールサーバ(Radish)では同じ状態でも通信ができるようです。
Radishを起動してTeraTerm(localhost:25)で接続してHELO<CRLF>でちゃんと
通信ができるのを確認しました。
netstatの結果も同様でした。
Radishのソースも見てみたのですが特別な処理をしているようには見えません。
上のような通信状態でクライアントと通信するために必須の処理などありましたらお教え願います。
何卒よろしくおねがいします。
391 :
Nortonがあると通信できないのは何故:2007/05/09(水) 15:00:42
ちなみにNortonを非難しているわけではありません。
以前、困ったものだと言ってしまいましたがあれは撤回します。
困ったものなのは今の僕の知識のなさです。
もういいから二度と来ないでくれ
>>390 SOCK_STREAMのブロッキングのソケットで1024バイトバッファで受信してるんだから、
1024バイト受信するか、connectした側がソケットをshutdown/closeするまで
ブロックするだろ。
どういう動作を期待してるの?
394 :
Nortonがあると通信できないのは何故:2007/05/09(水) 16:15:21
>>393さん
ご返事ありがとうございます。
再度確認してみましたがNortonのメールスキャン機能を外してTeraTermで
試したところ1文字TeraTermから送信するだけでサーバ側のrecvは処理を返すようです。
しかし、Nortonのメールスキャン機能を有効にして同じことをするとAcceptは成功する
のですが、何文字送信してもサーバ側のrecvの処理は帰ってこないのです。
>>390の内容からみて127.0.0.1:4766をローカルアドレスに持つNortonがデータの送信を
邪魔しているように思えるのですがどうでしょうか?
395 :
Nortonがあると通信できないのは何故:2007/05/09(水) 16:23:28
1024バイト読み込むまで待つような感じで書いてしまい誤解させ申し訳ありません。
今1024の代わりに1でやってみたのですが状況は同じでした。
>>394 virusかそうでないか判別してから溜めてたデータを送りなおすんだから
しょうがないだろ。
そのままスルーしてたら何のためのウィルススキャナだよw
>>359のソース見る限り、ソケット1本しかaccept()できないと思うけど、
>>390みると、nortonが接続してそれで終わりなんじゃないの?
その状態からTeraTermで接続しても、listeningのソケットがあるから、
connect()は成功するかもしれんけど、サーバ側がaccept()しないからそりゃつながらんだろ。
398 :
Nortonがあると通信できないのは何故:2007/05/09(水) 17:22:01
>>396さん、それはそうですね。データの送りなおし方がわかれば何かヒントになるかもしれないんですが。
>>397さん、複数のAccept可能なテストコード(終了処理は全然考えていない)を作って
試してみました。次にそのテストコードを書かせて頂きます。
試した結果やはり状態は変わりません。というかTeraTerm(クライアント)をconnectする前後でNortonとの接続
が確立するみたいです。しかし、Nortonは直接connectはしてきていません。
TeraTermを2つ起動しやってみたんですが、クライアントとの接続が確立するとそれに応じて
Nortonが、NortonのLocal Address=クライアントのForeign Address、NortonのForeign Address=クライアントのLocal Address
といった形の接続を確立するようです。
netstat -anoの結果としては、
TCP 127.0.0.1:25 127.0.0.1:2002 ESTABLISHED 2092(サーバ)
TCP 127.0.0.1:25 127.0.0.1:2004 ESTABLISHED 2092(サーバ)
TCP 127.0.0.1:2002 127.0.0.1:25 ESTABLISHED 3992(Norton)
TCP 127.0.0.1:2004 127.0.0.1:25 ESTABLISHED 3992(Norton)
です。
399 :
Nortonがあると通信できないのは何故:2007/05/09(水) 17:26:43
以下に複数Accept複数Recv可能なテストコード(終了処理は考えていない版)を載せます。
// Test12DoAcceptから呼び出されるスレッド(ひたすら受信する)
unsigned int _stdcall Test12DoRecv(void* pAnyParam)
{
char achBuffer[2];
::memset(achBuffer, 0, 2);
SOCKET a = (SOCKET)pAnyParam;
while (g_bTest12DoRecvAndAccept == true) {
::recv(a, achBuffer, 1, 0); //ここで処理が返ってこなくなる
::printf("recv msg[%s]", achBuffer); //Nortonを無効にするとrecvが返る
}
return 0;
}
// Test12から呼び出されるスレッド(ひたすらAcceptする)
unsigned int _stdcall Test12DoAccept(void* pAnyParam)
{
SOCKET s = (SOCKET)pAnyParam;
while (g_bTest12DoRecvAndAccept == true) {
SOCKET a = ::WSAAccept(s, NULL, NULL, NULL, NULL);
::printf("WSAAccept complete\r\n");
::_beginthreadex(NULL, 0, Test12DoRecv, (void*)a, 0, NULL); //TestDoRecv開始
}
return 0;
}
400 :
Nortonがあると通信できないのは何故:2007/05/09(水) 17:29:07
間違えました。g_b〜はいりませんでした。載せなおします。
// Test12DoAcceptから呼び出されるスレッド(ひたすら受信する)
unsigned int _stdcall Test12DoRecv(void* pAnyParam)
{
char achBuffer[2];
::memset(achBuffer, 0, 2);
SOCKET a = (SOCKET)pAnyParam;
while (true) {
::recv(a, achBuffer, 1, 0); //ここで処理が返ってこなくなる
::printf("recv msg[%s]", achBuffer);
}
return 0;
}
// Test12から呼び出されるスレッド(ひたすらAcceptする)
unsigned int _stdcall Test12DoAccept(void* pAnyParam)
{
SOCKET s = (SOCKET)pAnyParam;
while (true) {
SOCKET a = ::WSAAccept(s, NULL, NULL, NULL, NULL);
::printf("WSAAccept complete\r\n");
::_beginthreadex(NULL, 0, Test12DoRecv, (void*)a, 0, NULL); //TestDoRecv開始
}
return 0;
}
401 :
Nortonがあると通信できないのは何故:2007/05/09(水) 17:30:46
void Test12(void)
{
WSADATA sWSAData;
addrinfo sHints, *pInfo = NULL;
::memset(&sHints, 0, sizeof(sHints));
::WSAStartup(MAKEWORD(2, 2), &sWSAData);
SOCKET s = ::WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
sHints.ai_family = AF_INET;
sHints.ai_socktype = SOCK_STREAM;
sHints.ai_protocol = IPPROTO_TCP;
::getaddrinfo("localhost", "25", &sHints, &pInfo);
::bind(s, pInfo->ai_addr, pInfo->ai_addrlen);
::listen(s, 10);
// Acceptのスレッドを起動する
::_beginthreadex(NULL, 0, Test12DoAccept, (void*)s, 0, NULL); //TestDoAccept開始
getchar();
::freeaddrinfo(pInfo);
::WSACleanup();
}
以上です。
うむ。ごくろう。
人の意見を聞く気は無いらしいな
404 :
Nortonがあると通信できないのは何故:2007/05/09(水) 17:56:16
>>403さん。そんなことはないつもりですが、何かお気にさわりましたか。
なんでしょうか?
405 :
デフォルトの名無しさん:2007/05/09(水) 19:00:15
Winsockで、よくわからないことがありまして誰か助けて下さい。
「geekなぺーじ」のHTTPサーバサンプルを参考にコード書いてみたんですが、
SYNに対してのACKがすぐに返らないときがあります。
4秒程度、20回ぐらいリトライしているとようやくACKを返すんですが、
原因になりそうな事って何が考えられるでしょうか・・・
受けたパケットのチェックサムは問題なかったです。
他に注意すべき所があれば、ご教授のほどよろしくお願いします。
>>404 俺は
>>403ではないが。
もう少しまとめて、整理してから書き込んでくれ。
一つ質問があるごとにいくつも書き込まれると、正直、キツイ。
>>343、
>>390の件に関しては、プロトコルレベルでのサーバの挙動が問題だろうね。
「特別な処理」ではないと思う。
Nortonが間にいるから通信できない、ってわけじゃないでしょ。
>>405 それだけじゃわからんが、途中でパケットが落ちてるとか、
そもそも鯖が重くてSYNに反応していない等。
408 :
Nortonがあると通信できないのは何故:2007/05/09(水) 21:17:19
>>406さん、ご指摘ありがとうございます。
率直に言うと、netstat -anoでTCPの状態を見た場合、
確立している接続のForeignAddressがLocalAddressになっている接続があります。
Local Foreign
(1)TCP 127.0.0.1:25 127.0.0.1:2002 ESTABLISHED 2092(サーバ)
(2)TCP 127.0.0.1:2002 127.0.0.1:25 ESTABLISHED 3992(Norton)
(1)のForeignAddressが(2)のLocalAddressになっている
この場合、何故かサーバとクライアントの通信が行えません。
Nortonのメール送受信のスキャンをなくせば(2)がなくなり通信が行えます。
僕もはっきりとはわかりませんが、プロトコル以前にサーバとクライアントの通信ができていない
(Accpetまではするがsendもrecvも結果が現れない)ようです。
僕のイメージとしてはクライアント->NortonなどX->XサーバのようにNortonとサーバとの通信ができていないように感じます。
確かに特別な処理はなさそうなのですが、Radishなどの他のアプリではできるので
些細な違いがあるのかなと思って探しています。
どうぞご支援をよろしくおねがいします。
410 :
406:2007/05/09(水) 22:20:12
>>408 俺はSMTPレベルの話だと思っているんだけどな。
Nortonは
>>343のサーバからの送信を待っているんじゃないかな。
それが無いからHELOを溜め込んだままなんだろう。
TeraTerm - ( Norton - ) Radishのときと、TeraTerm - ( Norton - )
>>343のサーバの場合での、
両方のSMTPレベルでのフローを整理してみ?
>>408 そのnetstatの出力は、単にNortonが「サーバ」にソケット接続してることを示してるだけで、
「クライアント」との通信には無関係だと思うが。
nortonがあると、ってのは、nortonがNDISフィルタか、TDIあたりで「クライアント」のソケットに割り込んでるだけでしょう。
正直、情報が五月雨式に出てきて、何がなにやら分からないが、俺も
>>410のとおり
nortonのフィルタドライバが、25番ポートの通信をバッファして、SMTPレベルで解釈しようとしてるんだと思う。
telnetでつないで、HELOじゃない適当なデータいれても、サーバ側に届くってのなら、
まずは、
1. 「クライアント」は、shutdown、closeを呼んで、正規の手続きでソケットを閉じる。
2. 「サーバ」は非ブロッキングにするか、ブロッキングなら1バイトずつ読み込む。
3. send、recv、connect、acceptなどは、返り値を全て正常かチェックする。
をやればよいと思う。
複数の条件を一度に変えるんじゃなくて、一つずつ変えていけ。
マジレスするが、
ネットワーク関連のプログラミングをするWindowsでは、
Norton AntiVirusはアンインストールを推奨。
機能停めただけじゃ、まだまだ邪魔する気満々。なんなんだこいつは。
ネットワークプログラミングが課題で出たのですが解りません。
誰か助けて頂けないでしょうか。
問1 次を実行した結果を書きなさい
サーバー1
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define PORT 8427
int main(int argc, char* argv[]){
struct sockaddr_in server;
struct sockaddr_in client;
int s_wait;
int s_connect;
int client_len;
unsigned char* client_addr;
char buf[128];
bzero((char *)&server, sizeof(server));
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_family = AF_INET;
server.sin_port = PORT;
if((s_wait = socket(AF_INET, SOCK_STREAM, 0)) == -1){
fprintf(stderr, "サーバへのソケットが生成できません。 \n");
exit(1);
}
if(bind(s_wait, (struct sockaddr*)&server, sizeof(server)) == -1){
fprintf(stderr, "ソケットにサーバを設定できませんでした。 \n");
exit(1);
}
if((listen(s_wait, 5)) == -1) {
fprintf(stderr, "待ち行列が設定できません。 \n");
exit(1);
}
client_len = sizeof(client);
if((s_connect = accept(s_wait, (struct sockaddr *)&client, &client_len)) < 0) {
fprintf(stderr, "サーバに接続を要求できません。 \n");
exit(1);
}
if((close(s_wait)) == -1) {
fprintf(stderr, "ソケットディスクリプタをクローズできません。 \n");
exit(1);
}
client_addr = (unsigned char*)&(client.sin_addr.s_addr);
printf("connected to %d.%d.%d.%d.",
client_addr[0], client_addr[1], client_addr[2], client_addr[3]);
sprintf(buf, "HELLO, %d.%d.%d.%d!.",
client_addr[0], client_addr[1], client_addr[2], client_addr[3]);
if((write(s_connect, buf, strlen(buf))) == -1) {
fprintf(stderr, "ソケットへデータを書き込めません。 \n");
exit(1);
}
if((close(s_connect)) == -1) {
fprintf(stderr, "ソケットディスクリプタをクローズできません。 \n");
exit(1);
}
}
クライアント2
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define PORT 8427
int main(int argc, char* argv[]){
int ip[4];
struct sockaddr_in server;
int s;
int len;
char buf[512];
struct hostent* server_host;
server_host = gethostbyname(argv[1]);
bzero((char *)&server, sizeof(server));
bcopy(server_host->h_addr, (char *)&server.sin_addr,server_host->h_length);
server.sin_family = AF_INET;
server.sin_port = PORT;
if((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
fprintf(stderr, "サーバへのソケットが生成できません\n");
exit(1);
}
if((connect(s, (struct sockaddr*)&server, sizeof(server))) < 0 ) {
fprintf(stderr, "サーバに接続できません\n");
exit(1);
}
if((len = read(s, buf, sizeof(buf))) == -1) {
fprintf(stderr, "ソケットからデータを読み込めません\n");
exit(1);
}
if((write(1, buf, len)) == -1) {
fprintf(stderr, "ソケットへデータを書き込めません\n");
exit(1);
}
if((close(s)) == -1) {
fprintf(stderr, "ソケットディスクリプタをクローズできません\n");
exit(1);
}
}
問2サーバー1とクライアント2の間でメッセージ(文字列)がやりとりできるようにしなさい
手順は
送信:
1 標準入力(stdin)から文字列を配列bufへ読み込む
2 配列buf中の文字列をソケットに書き込む(write)
受信:
1 ソケットから文字列を読み込み配列bufへ書き込む(read)
2 配列buf中の文字列を標準出力(stdout)へ書き込む
この1問です ソースは自分でかいたのですが多分あっているかと・・・
どうかよろしくお願いいたします。
>>422 これはJavaの宿題スレにいけばいいのでしょうか
お前は自分が教わってる言語すらわからないのか
>>424 すいません 実験の授業なんで習ってないことをやってるんです
なんで習ってないことで分かっていないのに
分かったような振りしてそのままホイホイ進めちゃうのかなあ
何でも教えてもらえる身分である学生特有の悪い癖だな
ちゃんと言語の種類くらいは問題出した奴に聞けよ
C/C++スレ逝っとけ
427 :
405:2007/05/10(木) 10:01:24
>411さん
ありがとうございます。
今回のプログラムは単一のクライアントと試験的にイーサネットを介して通信させています。
同時に複数の通信を行っていないので、同時接続数は関係ないかもしれません。
教えていただいたBiotは試してみます。
SYNにACKをすぐに返さないのは、ポートを開いた後であることはMSネットワークモニタ3等を使用して
確認済みです。
bind、listen等を終えているのにもかかわらずSYNに対してのACKがすぐに返らず20回程度のリトライが
発生するようになります。
これはサーバ側でソケットのオープン→クライアント側で送信→サーバ側でクローズのような動作を
繰り返しているうちに発生します。
>>410 > 俺はSMTPレベルの話だと思っているんだけどな。
問題を切り分けるのに telnet 使うといいかな。
> telnet MAILSERVER smtp
220 MAILSERVER ESMTP
helo localhost ←ここ入力
250 SMTP
help ←ここ入力
(色々)
quit ←おしまい
>
こんくらいやって接続可能かどうか試すといいよ。
たくさんのアドバイスありがとうございます。
>>406さん、Radish(サーバ)×TeraTerm(クライアント)で通信を行い、Radishの詳細ログを見てみました。
見たところNorton(CCAPP)との接続をしていそうな感じはしません。RadishとTeraTermで直接やりとりをしているように見えます。
しかし、netstat -anoで接続状況を見ると相変わらずNortonのプロセスが
>>390のように接続を確立しています。
ログ2行目のようにSMTPはクライアントが接続したときサーバはすぐに220〜のメッセージをクライアントに
送信するようなので、自作サーバ(
>>400のプログラム)のTest12DoRecv関数の最初で同様のメッセージを送信するようにしたのですが
それもTeraTermには届きませんでした。
RadishではすぐにTeraTermにログ2行目のようなメッセージが受信されます。
まったくもって謎です。
以下詳細ログ
SMTP-SERVER Connected from localhost[127.0.0.1]
SMTP-SERVER > 220 localhost.localdomain SMTP Radish 3.0.0-b035; Thu, 10 May 2007 12:22:32 +0900
SMTP-SERVER < HELO (TeraTermでHELO<CRLF>を入力)
SMTP-SERVER Connected from localhost[127.0.0.1]
SMTP-SERVER > 250 localhost.localdomain Helo localhost[127.0.0.1], Pleased to meet you.
SMTP-SERVER < QUIT (TeraTermでQUIT<CRLF>を入力)
SMTP-SERVER > 221 closing connection
SMTP-SERVER DisConnect
>>406さん、また適当にhoge<CRLF>などとTeraTermから入力するとサーバからエラーメッセージがちゃんと届きます。
>>412さん、telnetで127.0.0.1 [25]につないでもホストへ接続できませんでしたと出ます。これはRadishがサーバでも同じでした。
なのでTeraTermでlocalhost:25で接続してHELOではない適当なHOGEなどの文字を送ってみたのですが、Radishではちゃんと受信したらしくエラーメッセージが返ってきました。
自作サーバでは受信できていないようです。
>1. 「クライアント」は、shutdown、closeを呼んで、正規の手続きでソケットを閉じる
HELOコマンドをホストに送信してすぐにshutdown、closesocket等を行うクライアントを作りためしてみましたが、
自作サーバではAcceptまではするのですがHELOを受信できませんでした。
そして次にRadishに対して自前クライアントでHELOを送りshutdown、closesocketすると意外なことがわかりました。
そのときのRadishの詳細ログです。
SMTP-SERVER Connected from localhost[127.0.0.1]
SMTP-SERVER > 220 localhost.localdomain SMTP Radish 3.0.0-b035; Thu, 10 May 2007 13:39:02 +0900
SMTP-SERVER < QUIT
SMTP-SERVER > 221 closing connection
SMTP-SERVER DisConnect
意外だったのはHELOの受信記録がなく送信していないQUITの受信記録があることです。
皆さんの意見をもとに考えるとNortonがHELOを正しいSMTPコマンドと解釈せずに捨てて、
shutdown、closesocketしたことでNortonが勝手にQUITを送っているのかなと思いました。
すいません。
>>430の意外だったのは僕のバグでした。
sendの直後にshutdownをしていたのでそれで送れていないだけでした。
でも送っていないQUITを受信しているのは変わりません。
やっぱりNortonがSMTPレベルで仲介していると考えるべきなのでしょうか。
以下自前クライアント(HELOを送信後終了)です。
int iRet;
WSADATA sWSAData;
addrinfo sHints, *pInfo = NULL;
::memset(&sHints, 0, sizeof(sHints));
::WSAStartup(MAKEWORD(2, 2), &sWSAData);
SOCKET s = ::WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
if (s == INVALID_SOCKET) return;
sHints.ai_family = AF_INET;
sHints.ai_socktype = SOCK_STREAM;
sHints.ai_protocol = IPPROTO_TCP;
::getaddrinfo("localhost", "25", &sHints, &pInfo);
iRet = ::connect(s, pInfo->ai_addr, pInfo->ai_addrlen);
if (iRet == SOCKET_ERROR) return;
char* pszMsg = "HELO localhost \r\n";
iRet = ::send(s, pszMsg, ::strlen(pszMsg), 0); // SMTP(HELOコマンド)送信
if (iRet == SOCKET_ERROR) return;
::Sleep(5000); // 念のためsendが完了すると思われる時間待つ
::printf("Send Msg[%s]", pszMsg);
iRet = ::shutdown(s, SD_SEND);
if (iRet == SOCKET_ERROR) return;
iRet = ::shutdown(s, SD_RECEIVE);
if (iRet == SOCKET_ERROR) return;
iRet = ::closesocket(s);
if (iRet == SOCKET_ERROR) return;
::freeaddrinfo(pInfo);
iRet = ::WSACleanup();
if (iRet == SOCKET_ERROR) return;
::printf("ClientTest01 end\r\n");
getchar();
>2. 「サーバ」は非ブロッキングにするか、ブロッキングなら1バイトずつ読み込む。
>>432の自前クライアントとエラーチェックを加えた
>>400-401での自前サーバ(ブロッキングで1バイトずつ読み込む)で試してみたのですが、
Nortonを無効にするとHELOコマンドのメッセージが自前サーバに受信されます。
Nortonを有効にするとHELOコマンドのメッセージが自前サーバで受信されません。
>2. 「サーバ」は非ブロッキングにするか、ブロッキングなら1バイトずつ読み込む。
今度は
>>400-401のrecvをWSAEventSelectで非ブロッキングにして試してみたのですがやっぱりさっきと同じです。
Nortonを無効にするとHELOコマンドのメッセージが自前サーバに受信されます。
Nortonを有効にするとHELOコマンドのメッセージが自前サーバで受信されません。
ただ一つ気になったのはNorton無効のときはクライアントがshutdownしたためか
WSAWaitForMultipleEventsは受信しなくても処理を返してきました。
しかしNorton有効のときはWSAWaitForMultipleEventsが返ってきません。
以下その待機処理の部分だけ書きます。
iRet = ::send(a, achBuffer, strlen(achBuffer), 0);
if (iRet == SOCKET_ERROR) ::MessageBox(NULL, "5", "err", MB_OK);
::Sleep(5000);
::printf("send message[%s]\r\n", achBuffer);
::WSAEventSelect(a, hEvent, FD_READ); // 非ブロッキングモード
while (true) {
::memset(achBuffer, 0, 1024);
// Nortonがなくクライアントがshutdownすると受信しなくても返ってくる
// Nortonがあるとここで返ってこなくなる
ulRet = ::WSAWaitForMultipleEvents(1, &hEvent, TRUE, WSA_INFINITE, FALSE);
if (ulRet != WAIT_OBJECT_0) ::MessageBox(NULL, "8", "err", MB_OK);
iRet = ::recv(a, achBuffer, 1, 0); //ここで処理が返ってこなくなる
if (iRet == SOCKET_ERROR) ::MessageBox(NULL, "6", "err", MB_OK);
if (iRet > 0 && iRet != SOCKET_ERROR)
{
::printf("recv msg[%s]", achBuffer);
}
}
>3. send、recv、connect、acceptなどは、返り値を全て正常かチェックする。
チェックしてみましたがどれも正常でした。
>>413さん
確かにそれでいいかなと思ったのですが、他のメールサーバでは普通に通信できているようなのでその理由が気になります。
また、実はPHPのmail関数を受けるためにローカルだけで動くメールサーバを作っているのですがApacheもNortonと同じような形で仲介してきて
通信が行えなくなります。
Apacheを止めるとPHPも動かなくなるのでこればかりは避けられません。
>>428さん。telnetだとRadishでもつながらなかったのでTeraTermでやってみました。
結果としてNortonが有効なときはRadishはTeraTermと通信可能。自前サーバ(
>>400-401)はできませんでした。
皆さん、アドバイスありがとうございます。
でもはっきりいってまだ原因がさっぱりわかりません。
何か検索するキーワードなども教えていただければうれしいです。
例えばnetstatしたときのサーバプロセスの外部アドレスをローカルアドレスに持つNortonが存在する状態
TCP 127.0.0.1:25 0.0.0.0:0 LISTENING 3896(サーバ)
TCP 127.0.0.1:25 127.0.0.1:4766 ESTABLISHED 3896(サーバ) //この外部アドレスと
TCP 127.0.0.1:4766 127.0.0.1:25 ESTABLISHED 3992(Norton) //このローカルアドレスは同じ
こういった状態が正式にはなんという状態なのかもわかりません。
素人で申し訳ありませんがよろしくおねがいします。
ついにできましたー!
原因を聞いて怒らないでほしいのですが、サーバのメッセージの最後に<CRLF>をつけていないためだったようです。
SMTPプロトコルの参考にしていたサイトがあったのですが、
そこにはサーバ側は\r\nをつけないような表現があったのでつけていませんでした。
で、皆さんの言うとおりプロトコルレベルの問題かと思いRadishのサーバのメッセージ送信関数を見ていたら
最後で<CRLF>をつけているのがわかり、早速つけたところ動きました。
本当に長い時間付き合っていただきありがとうございました。
素人なものでまたくだらない質問をするかもしれませんが、何卒よろしくお願いします。
死ね。
>>437 > SMTPプロトコルの参考にしていたサイト
なんで RFC に頼らずそんなものに頼るんだ?
何のためにテンプレに入ってると思ってるんだ。
次からはコテつけてくれ。絶対に答えないから。
原因を聞いてみんな怒っている。
嫌われ者は嫌われる理由があるものだ。
LFだけだとsegmentationfaultする処理系もあるな
思わない。
基本的な勘違いで皆さんのお手をわずらわしてしまいすみませんでした。
TCPって分割はされないんだっけ?
>>446 分割と言うか、send 側で write+flush した分だけ read 出来ると仮定してはいけない(仮定できない)。
但し、send 側で flush したデータ位置で recv 側の受信 flush が呼ばれる事は保証されてたと思う。
>>447 今 RFC 読み返したのでちょっと補足。
> send 側で write+flush した分だけ read 出来ると仮定してはいけない(仮定できない)。
これは「一度に read 出来ると仮定してはいけない」ということ。
送信側/受信側の TCP レイヤに依存する。
> send 側で flush したデータ位置で recv 側の受信 flush が呼ばれる事は保証されてたと思う。
送信側が直ちに送出するのは保証されてる(must)。
受信側は実装依存っぽく読めるけど、そうしない理由もないし、そうでない実装も見たこと無い。
flushのあとにsendがまた呼ばれて、
かつ、再送が絡んでくると、保証できなくのでは?
450 :
448:2007/05/14(月) 18:30:56
> The exact push point might not be visible to the receiving user and
> the push function does not supply a record boundary marker.
ごめんなさい...orz
recv側のflushって?
452 :
デフォルトの名無しさん:2007/05/14(月) 22:44:18
ソケットを使ってヤフーから株のデータをダウンロードするソフトを遊びで作っています。
ループを回してhtmlを取得するようにしているんですが、connection reset by peerと言うエラーがrecvで出まくります。
いったんクローズして再接続しているんですが、エラーの原因と対処法を教えて頂けないでしょうか。
よろしくお願いします。
request/responseのヘッダ晒してみ
454 :
448:2007/05/15(火) 02:24:17
>>451 recv 側のライブラリ作ってみればわかる
例えば通信を暗号化して送出する場合、複合するためにはデータ開始位置とデータ長が正確に受信できないといけない
もちろんデータは可変長
現在recv出来るデータが全部なのか、分割された先頭部位なのか、後続部位なのかってどうやって判断したらいいの?
TCPヘッダ
それはFAQだよ。
結局TCPでもUDP同等の実装が必要なのか?w
>>455 > 後続部位なのか
これはあり得ないだろ常識的に考えて…。
非同期通信では十分ありえる
TCPは分割の可能性はあっても、順番の入れ替えは無し
UDPは分割されないけど、到着順入れ替わったりロストしたりする
あのさ、なるべく多くの数のハンドルを待ちたいんだが、WaitForとかselectとか
色々あると思うけど、どれが一番いいかねぇ
>>463 WaitForってことはWinsockだよね?
ならオーバーラップI/O
FD_READが呼ばれたときにイベント処理をすると
TCPでデータ分割が発生した場合にFD_READが複数回呼ばれるじゃない
最初のFD_READで全部じゃないと判断したら
全部集まるまでFD_READが呼ばれる度にキャッシュしていかないといけない?
最後に全部揃ったら最終処理をするような感じ?
これってすげーめんどくさいんだけど
もっとスマートな方法はないの?
ない
FD_READが来たときに複数回recvすることも出来るし
最初のFD_READ内でrecvしないという手も無くはない。
対処療法にしかならないけど。
>これってすげーめんどくさいんだけど
昔に比べれば随分便利になった訳だが
>>465 selectでMaxSize変えてって感じかねー。10000とかにしていいのかなぁ。
すごく遅くなりそうだけど。
>>466 CreateIoCompletionPortとかかな。あれいまいち情報少ないし、
使い方がよくわからないんだよね・・
>>471 10,000ビットのビットマスクの管理もちょっと考えないとものすごく時間食うよ。
>>467 もう一段上のデータレイヤ考えて
データ区切りが来るまで読んで返すとか、
所定バイト読んでから返すとかすれば?
言ってみたかったのか?
WINSOCKはいくらMaxSize変えても、selectは
64以上待てない
CreateIoCompletionPortの引数の同時に実行できるスレッド数ってのがいまいち
よくわからん。
これはGetQueuedCompletionStatusで待つ側のスレッド数を指定すんのかな?
Get...で100個のスレッドが待機していて
キューにタスクが300個残っていたとしても
100スレッド全部同時に実行する必要はないでしょ?
現実にはCPU(コア)数だけしか同時には実行出来なくて
それ以上はタイムスライスを与えて切り替えているわけだから。
じゃあ、↑の状態のとき、いくつまで(同時に)実行するのかは
どうやって決めるか、と。
もちろん、決める必要(方法)が無い場合、100個同時に実行中状態になるけどね。
うーん、select的な発想だとディスクリプタを待つのになんでスレッドと
関連付けされちゃうのかなあみたいな・・
1スレッドでGetQueuedCompletionStatusで同時に待てるハンドルは64とかの
制限はないんですかねぇ。MSDNには特に制限書いてないから、リソースの限界
までって感じになるのかな。
しかし、unixは結局pollになるんだよなあ。。
完了ポートに関連づけることのできるハンドル数に
制限はなかった。
うーん、ちょっと状況というか目的がむしろ逆で、現状複数スレッドで
それぞれIO待ちになっているんだけど、スレッドが消費するリソースを軽減させるために、IO待ちを一つのスレッドにまとめて、IOが完了したら再び各スレッドに処理を渡すみたいなのを考えてるんだけど、色々と難があるなあ・・
>>482 えーと、まず複数スレッドでI/O待ちという状態が
片方でaccept,片方でconnectみたいな全然別のものというならまだしも
もし、1接続1スレッドなどということを考えているのなら
select系で効率を求める以前に、作り方が非効率すぎるだけ。
もちろん、作るのはその方が簡単だけど。
>もし、1接続1スレッドなどということを考えているのなら
>select系で効率を求める以前に、作り方が非効率すぎるだけ。
うぅん?同期タイプの設計って、普通1スレッド1コネクションだと思うど。。
ServletとかApacheとかもそうだし。シングルスレッドでselectが良いと
言うこと?squidとかはそうだけど。
非効率じゃない設計ってのがなにを想定してるのかよくわからんなあ・・
Apacheは効率なんて求めてないとは言わないけど、優先度低いでしょ。
だから、あんな非効率(ただし移植性と互換性重視)な作りにしてる。
ていうか、Servletこそスレッドプール使ってるじゃん。
「最小限+α程度のスレッドを用意して、必要なときに必要な数のスレッドを動かす」
がスレッドプールの使い方だよ。
「どのスレッドがどのコネクションに対応している」なんて
Servletには無いはず。
リクエストが来た時点で、空いているスレッドで処理を開始するだけ。
いや、糞実装は知らないけど、普通のAP鯖は、ね。
もしかして、その程度も知らなかったの?
あ、もしかしたらservletでも
acceptするたびに毎回スレッド作っていると思っていたのかね。
squidの作りが、「シングルプロセッサでディスクI/Oが無ければ」
「充分に効率を求めている」と言える作りだよ。
これにマルチプロセッサ(とI/O待ち時間)を生かすことを考えると、
普通はスレッドプールになる。
んーと、なんかわかってるんだか、わかってないんだかよくかんない人だなあ。。同期か非同期かって話と、スレッドを動的に作るか、スレッドプールから持ってくるかってのは別の話なんだよね・・
サーバとか作ってみるとわかると思うけど、
1. 同期・ブロックタイプ。各スレッド/プロセスでコネクションを処理
2. 非同期タイプ。シングルスレッドで非同期にrecv/sendを繰り返し処理
の大きく2つに分かれてて、他にもハイブリット的な設計もあると思う。
>もしかして、その程度も知らなかったの?
いや、別に知識くらべをしたかったわけじゃなくて、もしかして詳しい人
かなと思ってて。まあいいや。。
いやだからね、一般的に「スレッドプール」という単語は、
「毎回はスレッドを作らない」という意味ではなくて
「沢山のジョブを、少数のスレッド群で処理するやり方」という意味合いがこめられてるの。
だから、数千〜数万のコネクションがあっても利用するスレッドは少数で
実際にリクエストが来て処理を開始する時点で、任意のスレッドに処理させるの。
このリクエストは、コネクション数とは直接は関係しないわけ。
「スレッドプール」という単語、検索してみた?
たぶん、あなた、俺の言ってること全然わかってないよ。
あぁ、Keep-AliveなしのHTTPリクエストみたいに瞬間に終わるものだけを想定
してるからそういう勘違いをするんじゃない?
例えばtelnetみたいなの考えてみなよ。つなげっぱだったらどうなると思う?
スレッドプールが10で、10クライアントが接続してきてそのまま接続継続して
て、次がきたらどうなる?接続がスレッドを占有する場合もあるんだよ。
HTTPだってKeep-Aliveが長かったり、HTTPプロキシだったら上位のレスポンスが遅れればそれに近い状態になるんだよ。
ネットワークの場合はスレッドプールが単なる計算タスクの処理群とかと違って、接続数とスレッド数が絡んでくるんだよ。
WM_CREATEにおいて、char配列の中身を全てエディットコントロールに
表示させているのですが、何故かスクロールバーが自動で下までスクロールされません。
//char配列の表示
SendMessage(hLog_s, EM_SETSEL, 0, -1);
SendMessage(hLog_s, EM_SETSEL, -1, -1);
for(i=0; i<10; i++){
if(lstrcmp(logs[num][i], "*")!=0){
SendMessage(hLog_s, EM_REPLACESEL, 0, (LPARAM)logs[num][i]);
SendMessage(hLog_s, EM_REPLACESEL, 0, (LPARAM)"\r\n");
}
}
return 0;
しかし、ボタンを押したときにこれと同じ動作をさせると、
スクロールバーが自動で下に移動し、最後の行が表示される状態になります。
これは何故WM_CREATEだとスクロールしないんでしょうか?
>>491 何言ってんの?
もしかして、TCPで細分化されてしまうと
別のスレッドで続きを再開することが出来ないとでも思ってるの?
いや、あなたの書くコードがそういう糞コードだというなら、そうかもしれないけど。
telnetだろうがHTTP/1.1で複数こなそうが
あるいは、HTTP/1.1パイプラインで結合されようが
「スレッドとコネクションが密接な関係がある」なんて
グローバル変数使いまくりのコードでもなきゃ、有りえないって。
コネクションと、それに伴うデータ(中途まで受信したリクエストも含む)は深い関係がある。
でも、「そのリクエストを全て受け取った時点のスレッド」、つまり
「そのリクエスト内容を処理するスレッド」は、
コネクションとは何の因果関係も無いよ。
SOCKETさえ持っていれば、どのスレッドで処理しようと構わない。
途中まで受け取ったスレッドと今回のスレッドが別、
プロセッサも別でも一向に構わない。
それに、そもそもリクエストがどうではなくて
スレッドプールを利用できるかどうかは、処理の粒度に依存するものであって
細切れで待ちが多いネットワーク処理がスレッドプールに最適というだけだから。
まあ、こんなに丁寧に説明してるのにまだ理解できないというのは
全く理解する気が無いのだろうから、もう説明は止めるよ。
あなたの言う事が正しい、で結構。
うーん、上の1、2以外にもっと効率のいい方法があると言ってたんだよね?
擬似コードでいいから、ちょっと書いてみてよ。
なんか知識はあるけど、やったことない人なのかなんなのかよくわからんなあ。
Apacheよりも効率のいいサーバ設計とやらを書いてみてよ。
と思ったけど、もう一度だけ。
telnetで10スレッドで10接続、この時に「スレッドが占有される」と言うけれど
「スレッドプールでのネットワーク処理」は、これ自体がありえないわけ。
つまりね、スレッドはrecvでブロックしないの。
ボススレッドでselect系を使って、recv可能であることを判定する。
そして、(recv自体をボススレッドで行うかはともかく)recvしたデータの処理はワーカースレッド群に任せる。
recv可能、あるいはsend可能であると判明したら(selectから戻ったら)
その旨を(SOCKETと共に)記してキューにためる。
そして、ワーカースレッド群に対して「処理があるからどれでもいいから起きて」と伝える。
ワーカースレッド群は、条件変数なりで待機していて、
ボススレッドからの指令がキューに貯まったら(処理が可能になったら)ブレークして処理する。
(「処理」とは単に1文字recvすることかもしれないし、HTTPレスポンスの動的作成かもしれない)
ここでsendする必要があるなら、これもボススレッドのselectに委ね、
続きの処理は再開したスレッドに任せることにして待機。
処理が完全に終わった時も、再び待機。
普通にネットワーク処理の効率を求めると
このようなやり方になる。
これが「スレッドプールを使ったネットワーク処理」で
これを効率よく行うためにIOCPがある。
ポイントは、「ワーカースレッドでは絶対ブロックしないように処理を作る」という点。
(ディスクI/Oはあっても、ネットワークではブロックしない)
少なくとも、「そういう形に作ることが可能である」ということ。
ここがちゃんとわかっていれば、
>>491みたいな発言は絶対出ない。
「スレッドプールでのネットワーク処理」ってのが君の知ってるタイプだけじゃないから食い違うんじゃないの?
俺が言ってるのはUNIXネットワークプログラミングのp.729 27.12のTCP事前スレッド生成サーバあたりだよ。これ教科書に載ってるような内容だぞ?なんで知らないんだ?どっちかっていうとスレッドプールのサーバってこっちの方が一般的だろうに。。
じゃあ「スレッドプール」という単語はちゃんとぐぐったわけだね?
で、ちゃんとgoogleの一番最初の項目くらいは目を通したよね?
俺はちゃんと最初から「」付きで書いてるし
少なくとも「俺の使っている意味」も
>>489で説明もしている。
で、まあ、当然、事前生成から応用することも想定できそうなもんだけど。
まあ、servletがどうのと言っていながら
AP鯖が同時接続数と同数のスレッド(数千単位)を動かしていると思っている位だから
想像力を想像する力が俺に足りなかったのかね。
あと、改行してよ。
でね、わかっていると思ったけど
「効率のためにはまずスレッドプールありき」ではなくて
「効率のためにはまずselect系ありき」なわけ。
だから、シングルプロセッサでI/O待ちが無いなら、スレッドなんか使わないほうが効率が良いの。
だけどマルチプロセッサを生かしつつselect系の利点を生かすためにスレッドを使い、
それを効率よく利用するために
「スレッドの再利用」ではない「スレッドプール」という方法になるの。
確かに単に「スレッドプール」と言うだけじゃ「タスクキュー」は含まれないかもしれない。
これは俺が悪かったね。
でも当然「必然的に伴ってくる概念」だとわかっていると思ったから。
いや、だからスレッドプール、スレッドプールと連呼してるけど、スレッド
プールを拡大解釈しすぎなんだよ。スレッドプール自体にワーカスレッドで
ノンブロックソケットにするなんて意味はないんだって。。
んなことわかってるよ。
つーか、どこに「スレッドプールとはノンブロックソケットにすること」と書いてある?
勝手に決め付けないでくれる?
だいたい、あなたこそ「自分の知ってるやり方だけが正しい」と決め付けてない?
俺は「効率よくやるにはselect+スレッドプールになる」。
では「スレッドプールを使って」「効率よく」やるにはどうするか
これを突き詰めていけば自然と
>>495のやり方になる、と言ってるだけだよ。
もちろん、他のやり方もあるよ。
あなたの言う、コネクション要求が来たら、切断されるまでそのスレッドを占有するやり方も。
でも
>>491みたいに「必ず占有される」わけではなく
>>495みたいに「占有されずにやる」方法もあるわけ。
>>490のリンク先を書いた人の言う、「非同期処理を伴うスレッドプール利用」は
間違いなく後者。
あなたが、そういうやり方を知らなかった、それだけでしょ。
「効率」というキーワードが無ければ、「あなたが想像したservletの処理」も正しいけど
servletがどうやって効率を求めているか想像出来なくて
当然それをsocket処理全般に応用する方法も想像出来なくて
「自分の今まで知っているやり方でやっているに違いない」と思い込むならそれで良いよ。
「ネットワークで」「効率の良い」方法、
つまり、「select」と「スレッド」をうまく複合させること
これを一度でも考えたら
普通は
>>495のやり方でスレッドプールを使う形に行き着く。
それをわかっている人なら
IOCPを「効率よい」「スレッドプール」のキーワードだけで
どんなものかおよそ想像出来るの。
蛇足だけど、何故俺が「スレッドプール」という単語だけで通用すると思い込んだか
もう一言だけ付け加えておく。
かなり最初の方でIOCPの名が出る前に、
>>466が「オーバーラップI/O」という単語を出してるだろ?
GetOverlappedResultで結果を得る奴。
(これはMSだけじゃなく、Winsockで標準化されている)
で、これにスレッドプールで結果を処理することを想定させた仕組みがIOCPだから。
確かに、Unix系で覚えた知識にスレッドプールという単語を加えても、意味不明だったかもしれない。
でも、Winsock2の知識、つまりOverlappedI/Oの知識があるだけでも、簡単に想像できたはず。
(
>>1のWinsockFAQを読むだけでも、「効率にはOverlappedI/O」で
「IOCPはさらにそれを推し進めたもの」とわかる)
こんなことを勝手に脳内で仮定した俺が悪かったね。ごめんよ。
スレッドをブロックせずにリード待機する方法ってあるの?
まさか一定間隔ごとにスリープしてループじゃないよね?
理屈で考えるのは簡単だけどそれをプログラムで実装しようとなるとOSから組むほどのスキルと量になるわけで
これを既存のソケットで実装するにはどういう方法が一番簡単なのかというのを知りたいのですが
理屈で考えることも理想を語ることも馬鹿でも出来ることなので
作業工数との兼ね合いで一番容易な手法が一番優れた手法と言えるのですよ
>>488 > サーバとか作ってみるとわかると思うけど、
> 1. 同期・ブロックタイプ。各スレッド/プロセスでコネクションを処理
> 2. 非同期タイプ。シングルスレッドで非同期にrecv/sendを繰り返し処理
> の大きく2つに分かれてて、他にもハイブリット的な設計もあると思う。
レベル低!
「あると思う」て
>>505 > これを既存のソケットで実装するには
自分で実装しないのが一番。
>>505 > プログラムで実装しようとなるとOSから組むほどのスキルと量になるわけで
そんなに難しいことでもないと思うが...
横から失礼。俺は LAN 系の小さいシステムで昔ながら
の fork+exec っぽいのをスレッドでやったことしかな
いんだけど…。
セレクタが read 可能になったソケットに対してスレッ
ドプールが参照するリクエストキューに入れていくイメー
ジで良い?
read 可能になったからといって該当処理で必要となる
量のデータが read 可能かどうかはわからないと思うん
だけど、足りなかったらどういう動きになるの?
そういうことをちゃんと処理しないと行けない時は、
データ受けるところとデータ処理するところを分けて、
受けるところで一旦ジョブをサスペンドするんじゃないか。
その時スレッドプールにスレッドを返せばいい。
単純に処理わけはいいけどPINGコマンドのような即答を期待されるものは同じ処理系には置けないだろ
頭で考える理想を実際に形にしようとするとかなり細かいところまで要求される
実際に組んでみると応答順位がばらばらになったりと、即答されなかったりいろいろ問題が起る
決して簡単じゃない
もしライブラリがあるのならそれについて考えるほうがこのスレでは理想的だ
ライブラリの中身や一から作ることなどいくら議論しても無意味
>>506 そんな安いつっこみはいいからさ、サーバ設計モデルのタイプを一回ちゃんと
考えて、まとめてみると難しさがわかると思うよ。
で、まとまったら書いてみなよ。
>>509 そうでもない。javaだと、nioのSocketChannelとconcurrentの組み合わせになるけど、
interestingOpsの変更をワーカースレッドからやるとブロックするので、
Selector.select()と同じスレッドで実行しないとデッドロックする、など経験に頼るところが大きい。
あと、javaだと、ジョブをワーカースレッドにディスパッチするところがユーザー空間なのが弱い。
そもそも、ワーカーでの処理をnon-blockingにする、というのは、言語と無関係な技術だと思う。
>>510 ジョブの状態として保持する。具体的には、ジョブのバッファにnon-blockingでrecv可能な
データをコピーする。で、受信要求をあげて、眠る。
>>511 >データ受けるところとデータ処理するところを分けて、
>受けるところで一旦ジョブをサスペンドするんじゃないか。
そんなことしたら、スレッド効率が落ちるからしない。
CPUから見て、「時間のかかる処理」ってのは、ネットワーク、ディスク、各種デバイスとのI/Oしかない。
(メインメモリについては一貫性保持のために同期I/Oしかできないから考慮しない。)
で、あらゆるI/Oを非同期処理に置き換える。すると、一つのジョブは
CPUを使う処理→I/O進行待ち→CPUを使う処理→I/O進行待ち→
の繰り返しになる。なので、「CPUを使う処理」をある程度の数のスレッド、一般には
CPUのコア数以下のスレッドで並列処理し、「I/O進行待ち」になったら待ち行列に入れるってことになる。
I/O進行待ちを終えたジョブを、プールのスレッドに振り分ける部分ってのは、全てのジョブとスレッドが
関与する交差点になるから、ここを速くしたい、ってことでIOCPやepoll、kqueueなんかのフレームワークを作って、
カーネルモードで処理できるようになってきてる。
もちろん、全てのI/Oを非同期処理に置き換える、ってのは言うほど簡単なことじゃない。
ジョブの状態遷移図を把握して、一つの状態内で同期I/Oが必要とならないように状態を分割いていくのが定石だと思う。
OSを創るスレ?
516 :
匿名希望:2007/05/17(木) 15:42:08
はじめまして!
以下は、合計5組の2つ整数に対してその最大公約数と最小公倍数
を求めているプログラムです。
10 print "a","b"," gcm","lcm"
20 for i=1 to 5
30 read l,m
40 print l,m," ";
50 c=l*m
60 if l>=m then goto 100
70 w=l
80 l=m
90 m=w
100 r=l-int(l/m)*m
110 l=m
120 m=r
130 if r>0 then goto 100
140 c=c/l
150 print l,c
160 next i
170 data 10,20,5,25,588,133
180 data 58,369,1230,105
問 3個の整数の最大公約数と最小公倍数を求めるにはどのようにプログラムを書き直せばよいか。書きなおしたプログラムと、なぜその様に改変したかの説明を加え、提出しなさい。
この問、教えて下さいっ!!(>_<)
断る
518 :
匿名希望:2007/05/17(木) 16:17:35
お願いします〜!!命がかかってるんです(T_T)
命かかってるといえばさ
俺命書ける(誤植ではない)ってやってたよな
これ上げる(上に)とかさ
もう20代前半かー遊んどけばよかったな
>516
マギレヤキセ
さようなら
最大公約数を分散処理で求める話か?
>>514 後半、話がずれてない?
処理単位と受け取るパケット単位のサイズにずれがある時、
特に後者が小さい時にどうするか? って質問でしょ。
アセンブルしてから処理するしかないので、
パケット到着駆動じゃ苦しいロジックになる。
しかし、Javaの非同期IOを同期のInputStreamに繋げてるのってどうやってんだろうな。一度同期のreadLineとかに入ってたら関数スタック抜けるわけにも行かないから、中でバッファキューとソケットをwaitして処理もしつつ、自身のバッファのIOも待ってるって感じか?
遅レスかつ横レスだけど。
> 効率のためにはまずselect系ありき
select()って今となっちゃむしろ、効率が悪いことで有名でないの?
ビットマスクのサーチをしなきゃいかんし、
selectとともに使われる昔ながらのnon-blocking I/Oの仕組みに比べて
asynchronous I/Oのほうが効率が良いことは
>>3のUnix Network Programming
なんかでも述べられてるよね。
それでもUnixの世界では移植性や実装の枯れ具合から、
poll() + non-blocking I/Oが使われることが多いかと思いますが。
Win32ではkernelレベルで実装された汎用キューイングシステムである
IOCP + asynchronous I/OがNT3.5の頃から利用できて、MSもずっと
それを推奨してるわけだよね。これはselect()のような古い仕組みとは
全く違うといわざるを得ないでしょう。
select()やpoll()を使った手法はReactorパターン、
IOCP asynchronous I/Oを使った手法はProactorパターン
という呼び名でも知られていて、
ACEのようなライブラリを使えば、システム依存性をライブラリに吸収させ、
パターンレベルでそれらの機能を利用することが出来る。
kqueueが使えるシステムではそれを使ってくれたりするわけだ。
JavaのWin32のnioは、残念ながらIOCPを使ってはいないようだね。
524 :
523:2007/05/17(木) 21:50:55
525 :
523:2007/05/17(木) 21:53:17
さらにごめん。
×ビットマスク
○ビットベクタ
IOCPは下請けに使うには、ポリシー持ちすぎているんだよな。
"the principle of policy and mechanism separation"が弱い。
まあWindowsはバカチョンAPIしか提供しない方向だから仕方ないな。
>>526 kqueueとかと大して変わらなくないか?
じゃあなんで特許になってるんだ?
>>522 スレッドつくらずにJavaで同期と非同期つなげるのは無理だと思います。
ファイルのInputStreamを、FileChannelに置き換えるとかしないと。
>>523 499じゃないけど、select系ってのは、スレッドをジョブに1対1で貼り付けるのとの対比の意味で、
適当なトリガで引っ掛けてジョブを取り出して、もしくはコールバックしてもらって、指定したスレッドで処理する方式
のことを指してるんだと思う。
>>523の分類よりも上位の分類。
JavaのnioのSelectorは、現在のインターフェイスだと、
>>523の分類で言うReactorパターン、c10kの文書でいう
レベルトリガパターンしか表現できないから、IOCP使うのは無理ですね。nio2で対応してくるんでしょうか。
>>529 > JavaのnioのSelectorは、現在のインターフェイスだと、
>>523の分類で言う
> Reactorパターン、c10kの文書でいうレベルトリガパターンしか表現できないから、
> IOCP使うのは無理ですね。nio2で対応してくるんでしょうか。
posixでaioが規定されてるとは言え、win以外でのasync I/Oは
まだ移植性、信頼性他の面で色々と問題があるってことなんでないの。
待ってから改めてread()/write()でkernelバッファとの間でコピーするステップが
不要な分、効率いい筈なんだけどな。
ttp://www-06.ibm.com/jp/developerworks/java/040326/j_j-nioserver.html こことかはPiped使ってNIO非同期モデル上に同期ServletAPI
を構築する手法が書いてる。しかし、ジョブの粒度は
大きくなって、Request/Responseを完了するまでが
1つのジョブになるから、並行性は全て非同期のモデル
よりも落ちる。
でも、ここのソース抜粋すると
public synchronized boolean notifyRequestDone() throws IOException {
if (clientInputStream.available() <= 0)
requestReady = false;
ってなってるな・・・
これなら同期モデルでも次のリクエストなかったらキューに
戻すようにすれば、ほぼ近い形になるんだがな。
glibcのaio_xxxって単にスレッド立ててblocking callしてるだけなんだってな
IOCPとかはいらないから、Winでもepollを実装してもらいたいよ
epollって何に使ってるの?
pollで十分に感じるんだけど
教えてください
・select → 呼ぶたびに監視するディスクリプタを再設定する必要がある。
結果もすべてのディスクリプタを走査して探す必要がある。
・poll → 呼ぶたびに監視するディスクリプタを再設定する必要はない。
結果はすべてのディスクリプタを走査して探す必要がある。
・epoll → 呼ぶたびに監視するディスクリプタを再設定する必要はない。
結果は対象ディスクリプタだけが返るので、走査して探す必要がない。
OpenJDKのselectorのソースはがっつり
#define FD_SETSIZE 1024
ってなってる・・だめだめだな
>>536 それはkernelでサポートしてない場合に使う汎用版(sysdeps/generic)だよ。
あと、epollってのはselect/poll互換モード、つまり、各fdの「状態」を返すモードと
各fdが読み書き可になったというシグナルを返すモードがあるんじゃなかったかな。
後者は何故作られたのかというと、要は
複数のスレッドで直接同じfdset(pollfd)を待って、どれか1つだけがブレークする、というのを実現し
ボススレッドでの振り分けを不要にすることを目的としているんじゃないかと。
確認してない俺の想像だから
違ったらごめんよ。
>>542 レベルトリガとエッジトリガですね。
Linux限定のようですが、aioとio_setup(),io_getevents()...の組み合わせが
WindowsのAsyncI/O + IOCPに一番近いように見えます。
select/pollは読み書き可能かどうかを調べるものじゃないの?
ClientがSocketクラスを使用しServerがTcpClientクラスを使用する…というのは可能でしょうか?
TcpClientはではSocketをラップしているようなので大丈夫だとは思うのですが
サーバークライアント型のマルチスレッドチャットプログラミングをやっています。
サーバーはスレッドを一つ使い、accept()をずっとループさせています。
クライアントからの接続を受けると、そのクライアント用にスレッドを1つ作成し、
そのスレッドの中でrecv()をずっと回しています。
クライアントが終了したり接続したりするたびにスレッドの破棄、生成を行うわけですが、
_beginthread()と_CloseHandle()でそれを行うと次第に動作が不安定になってきます。
何かいい方法はないでしょうか?
スレッドを外部から停止させる、というのは
余程のことが無い限りやるべきではない動作のひとつ。
ホントに_beginthreadとCloseHandleなら、使い方が悪い。
_beginthreadexなら別の話
>>548 sunのスレッドライブラリにケチつけるの?
本気で?
recvしてるんだから
外部からソケットをクローズしてやると
recvがエラー終了するから
それを検知して内部からスレッドを終了する
>>547 >_endthread は、スレッド ハンドルを自動的に終了しますが、
>_endthreadex は自動的に終了しません。このため、_beginthread
>および _endthread を使用するときには、Win32 CloseHandle API
>を呼び出してスレッド ハンドルを明示的に終了しないでください。
事実上、_beginthreadexを使うしかWinでは選択肢はない
TCPの切断シーケンスについて質問です。
TCPのコネクションをcloseする際、タイミングによっては
A B
FIN−>
<−FIN
ACK−>
という風にオープン時のような3wayで終わっている場合があります。
RFCや文献を見ますと終了時はFIN,ACK,FIN,ACKと4TCPセグメントを
交換して終わる(それに応じてTCPの状態が遷移して
最後にCLOSEDになる)のですが、上記の場合ですと、AはCLOSING
から抜け出せない気がするんですが実際にはCLOSEDになっている
ようです。
おそらくこれは2番目のFINパケットを1番目のFINのACKとしても使用
しているから(オープン時と同様の3way hand shakeのように処理して
いる?)だと思いますが、だとすると疑問が残ります。このように
処理した場合、1番目のFINに対するACKパケットと2番目(Bから)の
FINパケットの到達順序がたまたま逆になった場合と、区別が付く
のでしょうか?
>>553 > おそらくこれは2番目のFINパケットを1番目のFINのACKとしても使用
違います。TCPの状態遷移図とにらめっこしましょう。
555 :
553:2007/05/21(月) 02:09:30
>>553 の図の補足ですが、1番目も2番目もACKフラグが立
っているFINパケットです。
RFC793の状態遷移図をみているのですが、
>>554さんのご指摘ですと、相手のFINを受けた
後はCLOSINGに遷移し、それぞれ相手にACKを
投げる同時クローズになる気がしますが、
>>553 に書いたようにACKは片方しか出ていませんです。
>>553 > FIN,ACK,FIN,ACKと4TCPセグメントを交換して終わる
> FINパケット
> ACKパケット
(用語を)正確に理解しようとしないから、理解が齟齬して、
言葉も誤用してしまうんだよ。
FINやACKはTCPセグメント上どう実現されているのか考えてみてくれ。
それからパケットダンプをよく観察せよ。
わからない人は反応しなくていいです
winsockにおいて、使用するソケットの数を制限する事は出来るのでしょうか?
acceptをずっとループさせているのですが、使用しているソケット数が10になったら
それ以上接続を受け付けないようにしたいのですが・・・。
11人目にはINVALID_SOCKETを返したいのですが、どうやら11人目は接続待ちキューに
ずっと待たされているようです。listen(sock, 0)にしてもやはりずっとキューで待たされています。
どうにかして待たさないように設定出来ないのでしょうか?
ちなみに、この設定だと12人目から、INVALID_SOCKETが返ってきます。
これは絶対に1人はキューでずっと待たされるって事ですよね・・・一体どうすれば???
プログラムが間違ってると思うよ
ソース晒してごらん
bind(sock0, (struct sockaddr *)&addr, sizeof(addr));
listen(sock0, 5);
len_s = sizeof(client_s);
//接続要求を受け付ける
while(1){
for(i=0; i<connect_num; i++){
現在に接続者数を数える();
if(10人以下だったら){
if(sock[i]がconnectされていない){
sock[i] = accept(sock0, (struct sockaddr *)&client_s, &len_s);
//受信用のスレッド作成
hThread_recv[i] = (HANDLE)_beginthread(recv_server, 0, NULL);
}
}
}
}
acceptした直後に叩ききってやるとか、
10になったらlistening socketを閉めるとか。
>>558 バックログで制限するより、
>>562の方法が良いんじゃないかと。
以下、MSDNのlistenのところから引用。
Compatibility
The backlog parameter is limited (silently) to a reasonable value as determined
by the underlying service provider. Illegal values are replaced by the nearest
legal value. There is no standard provision to find out the actual backlog value.
でもやっぱりバックログ制限でなんとかしたいかな
基本的な部分で手間かけるよりOSに丸投げしたい
>>562さんの通りに、listenのソケットを閉じ、9人以下になったら再度socket()、bind()、listen()を
行う事で目的の動作を果たす事が出来ました。ありがとうございました。
バックログは何かよく分かりませんので、適当にググっておきます。
それはさておき、クライアント側で接続/切断ボタンを超クリックしまくると、時々表示が変になります。
エラーは何も出ないのですが、最前面に出ているのにアクティブじゃなくなって、ウィンドウの一部が消え
背景にあるウィンドウが少しだけ見えるような状態です。これはログウィンドウに大量の文字がある時に起きるっぽいです。
ログウィンドウの最大サイズを3000バイトに制限したら正常に動作し、30000バイトにすると上記の不具合が起きます。
ボタンを連打出来ないような仕様にしてもいいのですが、出来ればあまりしたくありません。
どのようにすればいいでしょうか?
ちなみに接続ボタンを押すと接続/受信用スレッドが立ち上がり、切断ボタンを押すとスレッドが終了します。
>>565 クライアントで、socket通信を別スレッドに分けて、GUIスレッド(メッセージループをまわしてるスレッド)
の処理を滞らせないようにすれば良いと思う。
WinSockでウィンドウメッセージを使った非同期処理しても、socket送受信後、GUI表示への処理が
重ければ、その間メッセージループはとまる。
>>566 一応ソケット通信は別スレッドに分けています。
接続ボタン → サーバーに接続&メッセージ受信用のスレッドを作成
切断ボタン → そのスレッドを終了させる
recvをwhileでずっとまわしているので、メッセージによる非同期処理はしていません。
ボタンの処理や再描画等はウィンドウプロシージャで行っています。
メッセージループはWinmain()関数内で行っています。
「鯖接続」でブロックというオチ?
listenし直しはよくないです。し直している間に接続が来るので。
制限はaccept後にcloseした方がいいです。
し直してる間に接続がくるとどうなるのさ?
落ちてるWebサーバにがんばって繋げてるのと同じだよ
わからんな。
connectが内部でリトライするだけの話だろう。
バックログはコネクション数制限じゃない。
acceptしてcloseするのが正しい。
それが嫌だったら、メルコルータつかえ。www
>>572 まあ運良くつながる場合もあるだろうけどさ。
しかし、バックログにあるやつがcloseされたりもするだろう。
とにかくそれはサーバの起動停止を繰り返してるわけだから、もう
クライアントからみたら大変なことになってるわけだ。
ん・・・結局どうするのが正しいのでしょうか・・・
for(;;){
accept
if(num>10){
close;
}
}
closeってclosesocketですか?
WINSOCKならそうかもね
では、
>>565でいいんですよね。
listenし直さないと10人以下になったときに再度accept出来ないので。
じゃ次
>>579 ダメダメダメダメダメダメダメダメダメダメダメダメダメダメダメダメ。
お前才能無い。
いいんじゃね、体で覚えていけば
接続させて、アプリケーション層で、
「今忙しいから後にしてね」って答える手もある。
HTTPだと、503 Service Unavailable 辺りに相当。
>>579 listenじゃなくてsocket()とbind()だけでまたaccept出来るようになるんですか?
何だこのやり取りw
for(;;) {
Socket socket = server.accept();
if (num > 10) {
socket.close();
}
}
576と同じじゃん
だから576が正解なのにlistenしなおすとかトンチキなこと言ってるからだろ
では、10人が接続した後closesocketをして、その後誰かが接続を終了して9人になった時は、
新たな10人目はどのように接続すればいいのですか?
いままでのレスを読み返してみれば分かるかもね。
accept前にlistenソケットを破棄しても
acceptしてclientソケットを破棄しても
流れるパケットはまったく同じですおw
>>591 バカバカバカバカバカバカバカバカバカバカバカバカバカバカバカバカ。
お前やっぱり才能無い。
>>593 意味が分からない。死んだほうがいいんじゃない?
理解力のない質問者と、説明力のない回答者って事で。
あんまりバカを刺激しないほうがいいみたいよ。
Rubyスレとかバカが発狂してひどい事になってるし。
>>590 576の通りにしても出来なかったのですが・・・
何か勘違いしてませんか?俺が。
num;
for(;;) {
Socket socket = server.accept();
if (num > 10) {
socket.close();
}
++num;
ThreadStart
}
ThreadStart(){
...
--num;
}
BSDソケットAPIで行われたlisten()って命名はよくなかった。
listenソケットは閉じないでacceptしたソケットを閉じろと
>>601 !!!!!!!
そっちのソケットの話でしたか・・・。ようやく意味が通じました。ありがとうございます。
だとしたら、プログラムの仕様上、ソケットのディスクリプタを書き換えないといけないのですが、
sock[i] = sock[j]のような書き方で書き換える事は可能でしょうか?
なにこれw
どっちのソケットだかわかんなくなってんのかな
スレッド起こすときにソケットハンドルも渡しとけばいいだろw
acceptした直後に個数超えてたら閉じるだけやろ
スレッド起こす前に。
なんで書き換える話がでるんや・・・
仕様だろ
仕様です。添字が0〜9である事が重要なんです。
ってか、sock[i] = sock[j]で出来ました!
長い間付き合ってくれてありがとうございました m(_ _)m
チャットのプログラミングで、相手が落ちたというのはどうやって検知すればいいのでしょうか?
ウィンドウを閉じるなどの動作で終了した場合は、終了前にsend()を行う事で相手は終了を知る事が出来ます。
しかし、回線を抜くだとか、異常終了した場合、あいてはそれをどうやって知ればいいのでしょうか?
2つのプログラムを立ち上げて、普通にチャットをしてみました。そして、一つのパソコンの回線を抜いて、
もう一つのパソコンでsend()を実行したのですが、SOCKET_ERRORはかえって来ませんでした。
どうすれば相手の終了を検知できるのでしょうか?
定期的に ping 打って反応がなければ終了すればいいんでない。
>>610 pingとか打つのってなんか抵抗あるんですが、別に悪い事ではない?んですよね?
別に ping コマンドを打つわけじゃなくて、
生きてるかどうかを確認するためだけのやり取りをするってことね。
あ、そういう事ですか。そんな関数もあるんですね。
ちょっと探してきます!
send と recv でできるんじゃないのか?
もしかして、相手のプログラムは
自分の作ったプログラムじゃないのか?
両方とも自分の作ったプログラムです。
サーバークライアント型です。サーバーにメッセージを送って、
マルチキャストしてるのですが、そのマルチキャストの過程でSOCKET_ERRORを返した
ソケット(スレッド)は終了処理を行いようにしたいのですが、SOCKET_ERRORを何故か返してくれません。
api_readを使って、connect/accept等が完了したかどうかをチェックすることは可能ですか?
(send/recv以外の非同期完了を同じ方法でできないかなと考えているのですが)
普通はTCPの応答じゃなく、自身のプロトコルのレベルで相手が「OK」とか
を返してこなければ、死んでると考える
クライアントからは定期的にパケットを送る
各クライアント毎にパケットを受け取った最終時刻をメモっておいて
一定時間(上の期間の倍程度)受け取っていない相手は落ちたとみなす
sendして切断されてればエラーが帰ってくる
またはクローズイベントが帰ってくる
定期的に何でもいいから意味のないデータを送ってみる
SOCKET_ERROR帰ってこないなんてありえるの?
TCP上で基本プロトコルのレベルでPingを扱うのは危険だよ
TCPの性質上順次処理になるから過負荷がかかってる時に応答がタイムアウトする
>>620 送るパケットのサイズによってはフラッシュされずにエラーにならないとか
624 :
デフォルトの名無しさん:2007/05/25(金) 09:22:42
WinSock2プログラミングという書籍を参考に複数のクライアントに
pingを行う関数をワーカースレッドで呼び出してスレッド内でICMPの生ソケットを
作成しpingを送信してselect()でTimeOut値を最大に設定してpingの応答があるまで
スレッドが終了させないようにしています。
一台のクライアントに対してselect()はping応答があるまで待機するのですが
そのうち一台でもping応答があるとすべてのクライアントに発行している
ping応答が返ってくるという現象に悩まされています。
複数台のうち全部のクライアントがping応答しない場合は問題ないのですが
pingをマルチスレッドで複数実行する場合に何か注意しなければならない
ことでもあるのでしょうか?
ご存知の方ご指摘をよろしくおねがいします。
申し遅れましたがやりたいことは一台のPC(Windows)から60台程度の
クライアント(Windows)の活死を確認したいのです。
625 :
デフォルトの名無しさん:2007/05/25(金) 09:27:18
↑日本語がおかしかったので624は無視してください。
スレを汚して申し訳ないですが改めてお願いします。
WinSock2プログラミングという書籍を参考に複数のクライアントに
pingを行う関数をワーカースレッドで呼び出してスレッド内でICMPの生ソケットを
作成しpingを送信してselect()でTimeOut値を最大に設定してpingの応答があるまで
スレッドが終了させないようにしています。
一台のクライアントに対してselect()はping応答があるまで待機するのですが
複数台の場合その中の一台でもping応答があるとすべてのクライアントに
発行しているping応答が返ってくるという現象に悩まされています。
また複数台のうち全部のクライアントがping応答しない場合は問題ないのです。
pingをマルチスレッドで複数実行する場合に何か注意しなければならない
ことでもあるのでしょうか?
ご存知の方ご指摘をよろしくおねがいします。
申し遅れましたがやりたいことは一台のPC(Windows)から60台程度の
クライアント(Windows)の活死を確認したいのです。
もしかして
for でループして
192.168.0.0 - 192.168.0.255
まで廻してない?
627 :
デフォルトの名無しさん:2007/05/25(金) 10:46:32
>>626 そんな感じです。
全クライアント並行してリアルタイムに
Ping応答を受信しようと目論んでおります。
40台のクライアントがあれば
スレッドはforで40回廻して作成しています。
それが問題なのでしょうか?
NATとか考えなくていいなら、通常通信はtcp、生存確認は各クライアントから
サーバへ、udpでn秒に一度程度生存確認パケットを送るようにしたら?
n*m秒以上生存確認パケットが届かなければ死亡と見なすとか。
629 :
デフォルトの名無しさん:2007/05/25(金) 12:14:16
実際、クライアントのサービスアプリ開発中でそこに
生存確認パケットの送信も検討したのですが、
そのサービスの生存と切り分けてPCの生存のチェックをしたい。
との理由でpingを思い立ちました。
マルチスレッドのpingが無理なら
めんどうですが直列にpingを発行するしかないのでしょうか。
いちいち上げるな
>>625 >複数台の場合その中の一台でもping応答があるとすべてのクライアントに
>発行しているping応答が返ってくるという現象に悩まされています。
ここの意味がわからない。
ping応答がある、というのが、パケットモニタで見て、ICMP ECHO REPLYメッセージが
返ってくる、という意味なのか、
select()で、socketが選択されるという意味なのか。
select()されるという意味なら、実際にrecvfromで受信して、ソースアドレスを調べればOK。
WinSockのICMP書けるソケットがどんなもんかわからんが、
SOCK_RAWってアドレス選択受信できなかった気がする。
632 :
デフォルトの名無しさん:2007/05/25(金) 13:08:56
>>631 実際にselect()でのタイムアウト待ちではなく
setsockopt()による受信タイムアウトの設定と
recvfrom()によるソースアドレスも調べてみました。
すると、電源が落ちているPCのIPアドレスが入っていました。
もちろんコマンドプロンプトからPINGを打って応答が無いIPです。
いちいち上げるな
なんか、クライアントが通常終了した時はいいのですが、
回線を抜くなどして終了した場合に、サーバーが非常に重くなるのですが
これは仕様ですか?
「重くなる」って・・・
ここはサーバ運用についての質問スレではないと思うが?
>>635 ごめんなさい、説明不足過ぎました。サーバークライアント型のチャットプログラミングをしています。
サーバー側は、クライアントからのconnect()があると受信用のスレッドを立ち上げます。
その受信用スレッドのアルゴリズム的な問題じゃないかなとか思ったり・・・。
簡単に書いたので見てみて下さい・・・。
void recv_server(LVOID pParam){
変数いろいろ;
//クライアントからメッセージを受信
while(end_flag==0 && recv(sock[num], recvbuf, sizeof(recvbuf), 0)!=SOCKET_ERROR){
lstrcpyn((PSTR)code, recvbuf, 10); //コード抽出
if(lstrcmp(code, "****")==0){
マルチキャスト();
}
//配列の初期化
memset(recvbuf, 0, sizeof(recvbuf));
memset(addition_c, 0, sizeof(addition_c));
}
//終了処理
lstrcpy(any->name, "*");
any->flag = 0;
closesocket(sock[num]);
sock[num] = NULL;
}
>>637 正直、省略だらけのソースなので全然分からんけれど、
一つだけ質問。
プログラム上では、どうやって
「回線を抜くなどして終了した場合」を
検出しているの?
639 :
617:2007/05/25(金) 19:20:18
>>636 いや、確かにそれを使っているのですが・・・
そのaio_readなりaio_writeなりを使って、
connect/accept/closeなどの非同期完了を通知したいんです。
>>638 クライアントは終了直前(WM_DESTROY)に終了コード(9バイトの文字列)を送ってきます。
サーバー側では、それを受信したらend_flagを1にして、recvのループを抜けるように設計しています。
それとは別に接続フラグがありまして、accept完了したらフラグを1に、クライアントが接続終了したら0にします。
>>637のマルチキャストの時に
if(send()==SOCKET_ERROR && 接続フラグ==1){
回線を抜くなどして終了したとみなす
}
のようにしています。(接続してるはずなのにSOCKET_ERRORが出たときに異常終了とみなす)
ただ、これは思ったとおりに動かないので今はただfor(;;)send();のようにしています。
641 :
637:2007/05/25(金) 20:32:49
ちなみに、回線抜いてから2分後くらいにサーバー側のrecvはエラーコード10054を返して
そのスレッドは終了します。が、その2分の間がサーバーの動作が非常に重くなります。
これはなぜなのでしょうか・・・。
ビジーループになってるんだろ
ループしてるのはacceptしてるほうだと思われw
TCPのブロッキングなら取得サイズが0で切断という判断も出来る
(゚Д゚)ハァ?
>>642 ループを調べたところ、特にrecvのところでループしていませんでした。
>>643 調べてみます。
>>644 それは通常終了の時にしか0を取得出来ないような気がしますが・・・
accept周りを調べた後にやってみます
>>643 acceptの方もループの問題はないようです。
あと、
>>644ですが、recv()から進まないので意味ないですね・・・。
よくわからないが、最大数接続したらビジーループになる気がするが。
まあ、関係ないとは思うけど。
確かにループの中で、そのループカウンタに代入しているのは、どうよ? って感じ。
>>4で紹介されている
Visual Basicではじめるネットワークプログラミング超入門
という本、書店で見掛けないなぁ。ネットワーク関連はそういうものなのか。
川崎のヨドバシ、あおい書店、丸善を見たけど置いていなかった。
PC書籍コーナー大きいんだけどな。
>>649-650 一応その部分を変えてみましたが、やはりサーバーが凄く重くなってしまいます。。。
一体回線を抜いたときに何が起こってるんだろう・・・
・recvからの戻り値を、ちゃんと受信長として使え
・なんで、SOCKET_ERRORの判定を遅らせてるんだ
・異常終了時と正常終了時の処理を共通化しろよ。
FTPで接続時、デバッグ中はすべてのメッセージ受信できるんですが、
デバッグ以外では@のメッセージしか受信できません。何が理由か全然分からないので教えてください
@220-Welcome to the Yahoo! JAPAN GeoCities FTP server.
A220-Need help? Get all details at:
220-
http://help.yahoo.co.jp/help/jp/geo/ 220-
220-No anonymous logins accepted.
220 Yahoo!
>>654 recvからの戻り値は受信バイト数ですが、それを使う場面がないのでそのようにしています。
また、SOCKET_ERRORの判定を遅らせているとはどこのことでしょうか?(汗
正常終了と異常終了時の処理は共通化してみます
使え
>>657 -1or0だとエラーで終了、それ以外だと通常の処理、ですか?
ではそのようにしてみます。
ちなみに無限ループ系ではありませんでした。全てのループする可能性のある場所に
MessageBoxを仕掛けて確かめてみました。
ふざけてるのか
なにも変わりません・・・
ダメな奴だなぁ。どういう教育受けるとこういうコード書くんだ?
どっかからサンプルコード拾ってきて、自分のコードと比べてご覧。
すみません、独学で初めてまだ1ヶ月ちょっとなんです・・・。
本買うお金がないので、ネットにある情報だけを寄せ集めてがんばりました。
recv()に関しては他のサンプルと違う点は'\0'をつけるかつけないかくらいだと思うのですが・・・。
終端文字もsendしてるので私の場合はそれをしてないくらいかな・・・。
しかし、それが回線を抜いた時に重くなる事と関係しているのでしょうか?
世間様に出さないプログラムならそれでいいんじゃないか
ふと思ったのですが、回線を抜いたクライアントのソケットに対してsend()をしたらどうなるのでしょうか?
サーバーが重いのはそのせいのような気がしてきました。もしsock[i]の先のクライアントが回線を抜いた場合、
そのソケットにsend()したらどうなりますかね?SOCKET_ERRORは特に返ってこないっぽいのですが、
相手は落ちてるのにSOCKET_ERRORが返ってこないなんてことはあるんでしょうか?
setsockoptでsend()のタイムアウト時間を短くしたところ、重くなるのが一瞬になりました。
どうやら、回線を抜いたクライアントのソケットに対してsend()をしたのが原因だったようです。
まずsendはそんなにTCPの状態に敏感にエラーを返してくれないんだよね
非同期で実装した方が楽だったのかもしれないと今更ながら思ったり。
非同期のが何かとやっかいだよw
スレッドが同じだから前後の調和がおかしくなる
タイムアウト設定するとカーネル外部でループするからCPUが100%になる
ブロックにすればカーネルでイベント処理するから負担がない
>>665 重いんじゃなくて単にブロックしてただけじゃん…
>>668 非同期やっかいそうですね・・・。同期にして良かったですw
>>669 ごめんなさい。この場合、send()はすぐにSOCKET_ERRORを
返してくれるものだと思っていました。
返答が返ってこない限り上の層からはLANケーブルが抜けてるかどうかは
判断のしようがない。イーサネットとはそういうもの
思い込みでPGを組むとバグが発生した時に対処できない良い例だな
ここんとこの流れみててさ、
以前(2000年ごろ?)こういうので悩んでたなあと懐かしくなったよ
ここはお前の日記じゃない。
俺が悩んでたのは95年くらいだった
677 :
デフォルトの名無しさん:2007/05/29(火) 23:17:46
OSX 上で kevent でサーバ書いてるんだが、
accept した socket に、最初の EVFILT_WRITE イベントが来た
タイミングで send で EAGAIN が返るまで書き込んだ後、
EVFILT_WRITE が来なくなるんだが、そんなもんなんだろうか?
678 :
デフォルトの名無しさん:2007/06/01(金) 20:34:23
質問です。
長文ですがよろしくお願いします。
今UDPを使っての通信対戦つき2D格闘ゲームを設計しています。(スト2みたいなものです)
現在自分で考えた設計は以下のようなものなのですが、一般的な方法と剥離していないでしょうか?
・子は自分のコマンドを親に送る
キー入力そのものを送ると、通信ロスで抜けが出た場合うまくいかないと考えられる。
なので「昇竜拳コマンドが正しく入力されたか」はクライアントでチェックして、その結果を送る
・子からコマンドが届いた親は、そのタイミングでコマンドが成立したものとしてゲームに反映する
・親は常に「ゲーム全体の状況(キャラの座標、モーション、HPなど全て」を子に送りつづける
・子は親から送られてきた状況を画面に反映する(すでに反映した内容より古いものについては破棄)
。。。
子はキー情報を送る。親は状況情報を送る。という感じです。
子は完全なビュアーです。(予測画面遷移はさせます。昇竜拳の途中でラグってピタっととまるのは格好悪いので)
32bitあれば十分子から親にコマンド情報が送れる状況です。
ただ、毎フレーム子のコマンドを送るだけだと、届かなかった時「コマンド入力したのに技がでない!」という状況になってしまいます。
UDPは576バイトまでのデータなら(順序が入れ替わることなく)送れるようなので
毎フレーム「最新のコマンドから、100フレーム分くらいまでの過去のコマンドまでをまとめて送ってやる」
これなら100回のうち1回でも届けば、(100フレーム分の遅延があったことになりますが)コマンドが親に届くかなと期待しています。
ここまでひっぱっておいてなんですが、この方法だと遅延が起こるたびにどんどん遅延が累積してしまいます。
『「子はコマンド情報を送る」という考え方は間違いなのかなぁ』と悩んでいるところです。
何かしらアドバイスや、参考図書の紹介などをしていただけると幸いです。
よろしくお願いします。
ボタンとレバーの情報をゲーム開始からのフレーム番号を添えて
過去100フレーム分つけて送ればいいじゃん
ゲームは遅延するから無謀だと思うけどな。
インターネットなんていろんな遅延しまくるネットワークを複合的に使ってるから、タイミングとか同期とか無理。
マカはとりあえず氏ね。
サーバ側ってもう少し送信データ削減できそうだな。
例えば、通常は変更のあったキャラ座標などのデータのみ送信して、
一定時間ごとに全情報の送信を行い同期を取るようにする…とか。
あと気になるんだが、32Bit分のデータを1フレームごとに送りつけるとか言わないよな?
LAN以外でまともに動かなくなるぞ。
>>680 ネットワークゲームにはLAN専用という素晴らしい逃げ道もあるんだぞ。
ちゃんと設計ができていれば、
インターネットでナローバンド環境でも問題なく動くゲーム作れるし。
682 :
あい:2007/06/03(日) 00:54:07
例題1で用いた配列 atai とその100個の初期値が、
ある試験の100人分の点数だったとする。試験の合格点は65点以上で、
40点未満は追試がおこなわれる。このデータを集計するためのに以下のようなプログラムを作成せよ。
int atai[100] = { 37, 65, 74, 61, 51, 90, 89,78, 68, 69, 74, 74, 69, 44, 70, 78, 75, 70, 50,
25, 30, 72, 79, 67, 98, 98, 75, 79, 68, 45, 70, 66, 59, 61, 68, 34, 19, 71, 74, 76, 43, 72, 53, 48, 50,
87, 57, 85, 91, 74, 85, 61, 69, 61, 61, 32, 85, 86, 45, 71, 64, 83, 87, 59, 73, 75, 92, 59, 77, 54, 79, 98, 50, 61, 39, 53, 62, 62, 90, 33, 88, 73, 88, 86, 78, 38, 98, 97, 97, 79, 77, 97, 83, 44,
91, 72, 81, 85, 77, 45 };
(1)全員の平均点を求める
(2)合格者の人数を求める
(3)合格者の平均点を求める
(4)追試者の人数を求める
(5)追試者の平均点を求める
実行結果
全員の平均点は、68.6点です。
合格者は64名、平均点は79.8点です。
追試者は 9名、平均点は31.9点です。
このプログラミング作ってください。
>>682 そんなものこの世から消えてなくなるといいですね
最後の「このプログラミング作ってください。」だけ読んだ
英語でおk
This Proggramming tukutte kudasai.
>>682 スペースは全角スペースになってるから、自分で適当になおして。
#include <stdio.h>
void main(void){
int atai[100]={,,,,}; //ここは自分でコピペして
int i, sum=0, ok=0, ng=0, ave;
for(i=0; i<100; i++){
sum += atai[i];
if(atai[i]>=65){
ok++;
}else if(atai[i]<40){
ng++;
}
}
ave = 72;
printf("全員の平均点は%dです。", ave);
ok = 64;
printf("合格者は%d名、平均点は79.8点です。\n", ok);
ng = 9;
printf("追試者は%d名、平均点は31.9点です。\n", ng);
}
おい、投稿した後に気付いたけど、まったくネットワーク関係ねーじゃねぇか。
>>682氏ね
>>682 文字コードは UTF-8 な。歯磨いて寝ろよ。
begin-base64 644 682.cpp.gz
H4sICDA6YkYAAzY4Mi5jcHAArVTLattAFN3rK4YEwqhRXNuyZMl28yMlGHk0SURlyejhQoMhDoR2
Uyh01UWh3fSxaRddBVr6McZtPqP3zh05shO3pVQwaObeM+eeOfPYjRIRl6FkgyjNi0wG40NjdxWb
SlGkWT2SlGOZRaIeEuOgOD00jCgpWFAE0cMj9oCdGQw+u2sx17FYtwP/lsUcaH7TYp4PMQ9i2HxL
YRGjcJDrYL9JmK5DfQda2yGsjbk2NMC6UMP3qCmsT7wdjcW5rgvzfdKAORv4W6ihRTW7LmE7NvE6
8O94VNMDfgeaB9w+4RUWx4qv4oVmtwnnuao+8iusCzU8W3NhXZu0+m09xrjmRf2+rq04fdLjtqmh
f7atNXjEhX+siX7Z2gu/S61b+avHqAP9VWtBvS3SjPmOY8z6hiHiIM9ZGE2jUGZ6K3F381IImefD
UZpBYthfJTKZR8V6OC/CXo/OzwAgh3ur2dvyRALlJ+UojkRPwbQIvpXO2sZkqvn49TaFc9cxrXXR
vNOEUIXjurNCcaJkZzND0U7TKGTpRGYBVOUmV+6INJMmE2mSF9o05c8xVxk22JRh1lAbyDVtmzj8
CNCYlPnpcBSIRzTT7K8BZ6vRjMk4lxs8lZzfsBDDTJ2KMIV9kSxLyyTktEodmgZxKS29crRikkkR
5VGaVNI1sJDjCTwOascm6WPeajbgNN+g++QuGKEowYhmffGZLMosYQdq/nGcgvUHBLxH1Pus2XBM
dl+NaBW3Vq5J9msk+38kMWar9QdT2PUTqR24ffhgUGnWpRQmEKIcl3FQSA6IxkieRAmH84UDCYZC
F8zAshjJoyeSgx0zelbHAYI162ZJKAO7FuZ8T72+zSOLUQ9J0mOOfeStDQFkHpl3X8TqWGzJqoOn
94ksTLOhDMQp1zJullYF9PJWV7m6uHSnzDqZSMuCDQZsZ3n5Yfny7WL+aXn1Zfn66c+Lq8X88+J8
voNZOoLVRugyUKFlqrkK/H4xf7U4v1B4RQ0q4v5dlV48+/Hm6/X5JRQgNOnTe6Axz7H2xi1UmZq8
O7TdvCP/pO36+7frj+9IGyN69Oy/SCP3/0rYzPgFTs4uOCcIAAA=
====
どんなにくるしくても
おいしいものたべて
うんこしたらなおるよ! ∧ ∧∩
( ゚∀゚ )/
ハ_ハ ⊂ ノ ハ_ハ
('(゚∀゚ ∩ (つ ノ ∩ ゚∀゚)')
ハ_ハ ヽ 〈 (ノ 〉 / ハ_ハ
('(゚∀゚∩ ヽヽ_) (_ノ ノ .∩ ゚∀゚)')
O,_ 〈 〉 ,_O
`ヽ_) (_/ ´
ハ_ハ な お る よ ! ハ_ハ
⊂(゚∀゚⊂⌒`⊃ ⊂´⌒⊃゚∀゚)⊃
>>678です。アドバイスありがとうございます。
>>679さん
フレーム番号は添えますが、問題は「遅延して送られてきたコマンドは有効にするべきか」です。
遅延して送られてきたコマンドを全て有効とするならば、遅延が発生するたびにその後の全てのコマンドが遅延することになります。
ですが逆に切り捨ててしまうと、コマンドの「歯抜け」が発生してしまい「入力したはずが技が出ない」となってしまいます。
古過ぎる(20フレーム以上遅延している)コマンドは無効化。とかがいいんでしょうかね
>>680さん
確かに厳しいものの、最近は大抵の対戦ゲームが通信対応。なるべく対応したいなと思います。
後の方がおっしゃっているとおり、最悪「LANではいけますが、インターネットだと厳しいですけど、おまけ機能と思ってお楽しみください」という逃げ道もありますし。
>>681さん
サーバーが吐くデータは、現在の状況全てなのですが、意外とバイト数少なそうなのです。
キャラの座標。どっち方向向いてるか。モーションID。現在のモーションフレーム番号。その他ちょいちょいで32バイトもあれば十分そうです。
>あと気になるんだが、32Bit分のデータを1フレームごとに送りつけるとか言わないよな?
ダメでしょうか?ど素人ですいません。
UDPで友達(友人ケーブル。私光回線)と64bitのデータを送信しあうテストをしてみたところ、データは全て受信、遅延は21msという状況でした。
21msならば、1フレームちょい。入力から画面反映の遅延は、3フレーム程度なら違和感が無かったので十分かなと思ったのですが…。
>>692 たとえば
236+P が送られて、コマンドが解釈されて波動拳が出るまでのシーケンスは
1フレ目 2
2フレ目 3
3フレ目 6+P
として、これが発動して波動拳が出るまではモーションが8フレームある
入力が2,3と来て、その後3フレーム遅延してから6+Pが来たとするとき
2フレーム前から波動拳は成立したとして、モーションを頭2フレーム分
削って波動拳を出したことにすれば 操作感もフレームも損ねることなく
ゲームは進行可能。
書いてて穴だらけでげんなりしてきたが、まあこういうkとおをやろうと
してるんだよね?
>>693さん
細かくありがとうございます。
そのとおりです。CPU対戦であっても、通信対戦のホストであっても、入力から必ず入力は3フレーム遅らせてからゲームに反映させます。
ただ、
>入力が2,3と来て、その後3フレーム遅延してから6+Pが来たとするとき
ここの部分は違います。
これですと遅延のせいで技が出なくなってしまうと考えられるので、クライアントには以下のようなコマンドを送るようにさせます
1フレ目 「下キー押されてるぜコマンド」
2フレ目 「下キー押されてるぜコマンド」「右キー押されてるぜコマンド」
3フレ目 「右キー押されてるぜコマンド」「P押されてるぜコマンド」「波動コマンド成立してるぜコマンド」
コマンドはそれぞれ1bitで管理し、種類は現在20個ちょいあります。(32bitに十分収まりそうです)
そこ以外はおっしゃるとおりです。
「3フレーム分の猶予」の中から、遅延分を差し引いてゲームに反映させます。
裏を返せば、3フレームしか猶予がないので、3フレーム以上の遅延が出る通信状況ではラグっていることが目に見えてわかることになります。
基本的なところだけど、
UDPなのがガンなんじゃね?
TCP/IPではもっとダメだろ
それに入力されたコマンドを全部反映させてやろうとすることによる遅延は、TCP/IPだともっとひどいことになるぞ
>>696 PUSHもしらんのか?
TCP/IPって書き方もやめろよ。
それから
>>694のような状況でTCPが一番無駄なのは、不必要な場合の再送。
「遅延」だなんて片腹痛い。
>>697 PUSHとか関係なく、経路の遅延のことを言っているんじゃないか?
>>698 TCPなら遅延しないかというとそんなこともないわけで
以下NAGLEについてのどーでもいい話が続々
epoll_waitとかepoll_ctlなどはスレッドセーフかどうか知りたいのですが
どこを調べれば解るのでしょうか?
しかしソース読まんとわからんライブラリてクソだよなあ
前waitに入った後に別スレッドでctlでディスクリプタ足した場合は
それは有効なのかどうかがわからんときも困った。
どうも平気そうなんだけど保証がとれないんだよなあ。
>>703 マニュアル・リファレンスを信じることが出来るか、という話だよね。
マニュアルが信じられないなら ソースを見るしかない。
ブロック操作中に別スレッドから記述子を閉じたときどうなるかも
明示されてないことが多いんだよねえ
>>705 それは明示する必要ないッス。
他の「スレッド」からcloseしたら、そのディスクリプタは閉じられるッス。
>>702 ありがとうございます。
とりあえずソース読みます
>>704 じゃなくて、そもそも書いてないって話だろ
参考にはなるけどソースは一実装だからそれこそ信じられない。
それよりも仕様を明示するべきだろうに。
>>708 見つけにくいところにこっそり書いてあるんですよ。これが。
そうだね。書いてあるといいね。
711 :
704:2007/06/07(木) 07:45:23
>>709 manpageあたりに書いてありましたか?
できれば書かれていた場所を教えてほしいのですが・・・
712 :
704:2007/06/07(木) 08:16:25
>>711 fork,closeあたりのmanから入って旅をすればいいよ
知らないなら書かなくていいよ
714 :
704:2007/06/10(日) 17:03:50
>>712 いまだに見付けられないんですが、どこに書かれているのでしょうか?
man 7 socket
なんのレスかもうわからん
717 :
デフォルトの名無しさん:2007/06/13(水) 09:53:29
Win32API質問箱から誘導されてきました。
このwpeproみたく、socketの盗み見、編集をするためのAPIの名前のヒントをください。
dllのinjectionで割り込むのがスジでしょうか。
http://wpepro.net/ NEGiES version 1.57
みたいなやつを作ろうとおもってます。
ttp://hp.vector.co.jp/authors/VA036210/ 参照はioctlsocketにSIO_RCVALLでできるのまでわかっています。
でも、これだと編集はできないです。
winpcapを利用しても参照はできても盗み見るだけで、編集はできないと思っています。
過去ログはHTTP Errorで読むことができませんでした。
どなたか本スレの過去ログ場所を知っておられたら、そちらも教えていただけないでしょうか。
ドライバ フィルタ
wsock32.dllを自分で作ってオーバーライドだ
Winsock2でマルチキャストサーバ実装してをNTサービスで自動起動すると
recvfrom()で止まったまま受信してくれないことがあるんです。
手動起動の場合はちゃんと問題なく受信してくれるので一回目のrecvfrom()を
Windowsの起動時間で判断して遅延して行うことで逃げてるんですが
他に何か解決策はありますか。
722 :
デフォルトの名無しさん:2007/06/14(木) 21:06:42
>>722 そこいらへんはネットワークじゃなくてwindowsプログラミング。
>>717 NEGiESは思いっきりドライバ使ってるが?
725 :
デフォルトの名無しさん:2007/06/15(金) 08:01:38
>>723 スレ違い、ですかね?
>>724 Version 1.57から使ってます?
sysファイルがあるってことはつかってるってことか・・・。
ども、レスありがとうございます。
726 :
デフォルトの名無しさん:2007/06/15(金) 10:24:53
ローカルループバック 127.0.0.1 とか、自分と同一アドレスへの接続をスニファリングってどうやるの?
ほとんどのソフトでできないようなきがする。できるソフトがあったらおしえてください。
プログラミング関係ないやん
自分で実装しようとしているなら関係あるな
>>726 Unixでtcpdumpなら普通に出来る。
$ tcpdump -i lo
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
の第二引数のeventsって自分でメモリ確保しないとダメなの?
環境によって動いたりEFAULT返したりするんだけど・・・
もしかして今まで動いてたのはメモリ破壊起こしてたのにたまたま動いてたってことなのかな?・・・
>>730 自分で確保。 確保してくれるんだったら struct epoll_event **events じゃなければ
受け取れんだろうが。
>>726 linuxだったらとれるね。windowsだったらとれないね。
フィルタドライバつくったらとれるのかどうかは知らん。
LSPなら出来るけど、
WindowsのLoopback Adoptorをsniffするなんてほとんど意味ないんじゃないの?
ほとんど意味無いけどしてみたいという興味。
というかできないならできない理由を知りたい。
もともとWinsockがNetwork Adaptorないと動かない設計で、
有効な物理Adaptorがない時でも、
無条件でWinsockを初期化しようとするアプリを動かすために、
Loopback Adaptorというのを作った。
BSDのloopback interfaceとは、もともとの目的が違う。
だから、BSDのloopback interfaceの視点から見れば、不完全なもの。
738 :
デフォルトの名無しさん:2007/06/27(水) 17:02:42
ちょっと疑問に思ったんですけど、
tcpdumpってどうやってインターフェイスから直接パケットを拾っているんですか?
promisc
>>738 ぜんぜん「直接」じゃない。 わざわざそうするための特別なソケットにパケットを分岐させて
ユーザーランドに送り出す機能がカーネルに実装されている。 Winは良く知らんが。
Windowsでは、パケットを分岐させるフィルタドライバWinPCapを挟み込んで
横流ししてもらう。
Windowsってなぜか同じハードでも取りこぼし多いのは
構造の違いかな。
winsockです。
WSACleanup();は、WSAStartup()と対で、
一つのプログラムに、一つでいいんですよね。
プログラムの最後とか。
で、プログラムでマルチスレッドの作っていたのですが、
WSACleanup();は、他のスレッドの通信も切断してしまったんです。
WSACleanup();って、どうせプログラムの最後にしか書かないし、
もう、いらないんじゃないかと思ってきました。
WSACleanup();無しで、終了すると不具合とかありますか?
レベルが引く質問ですみません。よろしくお願いします。
744 :
デフォルトの名無しさん:2007/07/06(金) 11:52:35
ハンドルでもなんでも取得したものは開放と教えられますが
それは素人だましなので無視してOK
745 :
デフォルトの名無しさん:2007/07/06(金) 12:53:58
UDPでマルチキャスト送信をしようと思います。
TCPと比べて信頼性が低いとの事ですが、どれほどのものなのでしょうか?
ネットワークの状態にもよるとは思いますが、一般的にどれくらいの率で送信失敗するのでしょうか?
また、どのような理由で送信失敗することが多いのでしょうか?
>>746 電気的ノイズで落ちたりHubが落としたり途中経路のルータが落としたり
通信相手や自分の送受信バッファ溢れで落としたりと、
環境や状況依存なのでパケットロス率は実環境で長期的に計測しないとわからない。
>>747 ありがとうございます。とりあえずネットワーク的に繋がっていれば
何か特別な異常がない限り基本的にはパケットロスしないと考えてもいいのでしょうか。
UDPだとパケットロスした事も気付けないので、あまり信頼しすぎても問題なのですが。
一応、30人以上を想定した多人数でのチャットソフトを考えているのですが、
TCPによるユニキャスト送信の繰り返しをループで繰り返すのはどうかと思いまして・・・。
チャットはtcpか独自だね見るのは・・・
>>749 昔TCPでチャット作った事あるのですが、send()をループに入れたら動作が怪しかったです。
for(i=0; i<10; i++);みたいな感じでsend()してもメッセージが届かなかったり・・・。
ループの間にSleep(500)とかはさんだら普通に動いたんですけど、遅延がなぁ・・・
初心者ほど自分のコードの書き方がわるいとは考えず処理系や
プロトコル、OSの問題だと考えたがるものだね
というか、パケロスは 当然のようにあるものなのだから
それを考慮しないコードは全てウンコだろ
for(i=0; i<5; i++){
for(j=0; j<5; j++){
send(sock[j], sendbuf, sizeof(sendbuf), 0);
}
}
こういう書き方はよくないんですか?
>>753 sendの戻り値チェックを怠ってるし、アウトだね。
sendがエラーのときはどうする?送信バイト数が少なかったときは?
それらをわかってて無視してるならいいけど
結構前の記憶なのですが、一応sendのエラーチェックを行ったのですが、
特にエラーを返さなかったです。なので手の打ちようがなかった記憶が・・・
送信バイト数が少ないなんてありえるの?
>>756 仕様にそう書いてあるなら、ありえます。
RFCは聖典ではない。
仕様書こそが聖典なのだ。
そしておきゃく様こそ神。
RFCはプロトコルその他の仕様書で、
>>758の言っているのはAP:I仕様書。
>>752 対戦型アクションゲームや動画のストリーミングなら、(考慮した末に?)
ロスしたデータは無かったことにして動作するようにしても良いと思う。
「クライアントAが8フレーム前に技出してたんだ」とか「3秒前に表示すべきだった画面の左上、今届いたな・・」
とか後から気付いてもどうしようもない。
>>746 ピア間の実効帯域を超えて send すると盛大にドロップする。
そうでないときにはほとんどドロップしない。
WindowsとLinuxとの間でのUDP通信プログラムを書くことになりました。
LinuxのSocketプログラムの基本は理解しているのですが、
WinSockは初めてです。
初心者本として以下のもはどうでしょうか?
他にも何かお勧めがあれば教えてください。
WinSock2プログラミング―Windows Sockets APIによるネットワークプログラミング
のすべて
763 :
デフォルトの名無しさん:2007/07/06(金) 17:33:50
ネットで十分だと思う
765 :
デフォルトの名無しさん:2007/07/06(金) 19:07:11
ftpdでjpgファイルを複数受信して、そのファイルを読みこんで
処理するプログラムを作成しています。
opendirでファイル名を取得してfreadで読みこんでいるんですが、
ファイルの書きこみが終了したタイミングがわからないので
3つファイルがあったら、2つめまでを読みこむようにしています。
他に何かいい方法はないでしょうか。
アドバイスお願いします。
>ファイルの書きこみが終了したタイミングがわからないので
fflush();
ftpdつくってるんだろ、じゃあ、受信完了なんか
データコネクションが閉じられたときなわけで、自明じゃん。
、と思てしもた。
PASV?
>>765 ファイルの更新時刻で適当に判断するなり、送信完了時にフラグファイルを
送るなり、ftpdをハックするなり、好きにすればいいんじゃね
向こう(JPG送信側)がデータ送信し終わったら、クローズするんだとして、
そしたらこっちはパッシブクローズして、アプリ層でTCPからEOF受け取るまで
データ読み出せばOKかな・・・?
Cじゃないかもしれんだろ
ルーターでIPマスカレードしてるLAN内のPCから、
同じ様にルーターでIPマスカレードしてる別のLAN内のPCへ、
間にサーバーマシンを経由せずに、直接TCP接続する方法ってあるかな??
相手側のルーターでパケット破棄されちゃうから、無理だよね??
ルータの設定次第だな。んで板違い。
UPnPを喋る話?
(UPnP) が顔文字にしか見えないから困る
ダースベーダー犬
778 :
デフォルトの名無しさん:2007/07/07(土) 19:47:25
ヘイローキラーって売り文句のソフトのソルジャー思い出した
┌─┐
UPnPU
│э│
└─┘
┌─┐
UPnPU
│э│<ネプグラ君だよ ヨロシク
└─┘
781 :
デフォルトの名無しさん:2007/07/08(日) 16:27:35
ファンタジーゾーンだ
YA☆DA☆YO
おまえなんかきらいだー
┌─┐
UPnPU
│э│<冷たくしないでヨ
└─┘
>>748 UDP にすべきか TCP にすべきかは「抜けても大丈夫か」
で分ける。一回/日の時刻同期とか「抜けてもいいや」
なら UDP。
データに対して ACK なり再送なりを要求するなら TCP。
UDP で再送とかを実装するくらいなら TCP 使えよ、って
TCP の RFC にも書いてあった希ガス。
でもTCPにはウィンドウサイズがあるからなぁ
はあ
#include <netinet/in.h>
#include <sys/socket.h>
をインクルードして
struct ip ip_header;
とやると、
error: storage sizeof ip_header isn't known
となります。
netinet/in.hにstruct ipがあるのに
何でサイズが解らないなんてエラーがでるんでしょうか?
ないだろ。
790 :
デフォルトの名無しさん:2007/07/14(土) 11:00:47
>>788 struct ipの中で使ってる型が不明
UDPは特にトラブル無くてもパケットロスするぞw
>>790 返信ありがとうございます。
struct ipの定義をコピペして、メインのコードに直接定義したら
コンパイルが通りました。
謎です。
どのように解決すればいいのでしょうか?
ってよくみたらip.hじゃなくてin.hじゃねーか。
ip.hはincludeしてるのか?
オレさあ、ネットワークプログラミングってさあ
ヘッダーが山ほどあっていつも迷うから
思いついたもんは片っ端からインクルードしてる
これって良い習慣?
利用しないやつってコンパイル時に省かれるから
いいんじゃね
C++でソケットプログラミングするとき
お勧めのライブラリってなに?
Linuxだけど
ACEとか?
ACEの青っぽい本買った、暇無くて読んでない
800 :
デフォルトの名無しさん:2007/07/15(日) 22:30:08
TCP hole punchingを実験してみようかと思ったが
3個もglobal IPなんて日曜プログラマが自由につかえるかっつの
自由に使えるランデブーサーバーとかないのかよ
それにしてもUDP hole punchingでさえNATによっては使えないとか
機種の何%かは動かないのがあるとかなんなんだこれは…大した研究分野だよ
skypeとかだってほとんど中継ばっかなんだろホントは
よくわかんねーけど、global IPで実験するの?
なんたらパンチアウトってプライベートIP同士をつなげるんじゃねーの?
>>803 飛んでったパケットがそのまんま帰ってくるのを許す機能
>>800 なんでグローバル3つも必要なんだ?
サーバー1つで良いはずだが? ネットワーク環境3つって意味?
っていうか 今ではUDP自体セキュリティ的に飛びにくいから実用的ではないよ・・特に企業がらみ
ルーター買って設定無しで付けてるエンドユーザー向けならば
UPnPをソケットで直接叩いた方がまだ可能性は高い
806 :
デフォルトの名無しさん:2007/07/16(月) 01:55:04
>>801,802
こんな信頼性の欠片もない技法、実際に使う環境で動くことが証明できなきゃ意味内
>>805 2つのNATの外側とランデブーサーバーであわせて3つ
UPnP
>>806 最初に理想環境でテストしとかないと
実環境のときにトラブルシュートできないよ?
こういうのって学校や職場で最初に習わないのかなぁ
809 :
デフォルトの名無しさん:2007/07/16(月) 02:16:19
授業じゃないの?
>>806 固定グローバルという意味でなくて外側という意味ね 納得
あまりお勧めできないけど・・
自宅のPCで穴あけてサーバーにして
両クライアントはネット喫茶等々でテスト
どっちみち信頼性得るには 日曜プログラマレベルでは荷が重いよ
ルーターによって癖あるし テストで動かすだけなら簡単だけど
ロジックうんぬんを勉強しても意味無いカテゴリだよ
2年ほど前のスレにも書いたけど簡単に ホールパンチング
書いとくね
S=サーバー、 C1=クライアント1 C2=クライアント2
1、C1とC2が サーバーSにUDPを送る
2、(重要)C1から C2へ、C2からC1へUDPを飛ばす、このパケットはルー ターに阻止されるがルーターのテーブルに書き込まれるので
3、SはC1,C2から来たUDPのポート情報、IPアドレス返す
S->C1(C2の情報) S->C2(C1の情報)
4、C1,C2はそのIP、ポート番号を使い直接アクセス
仕事でIPv6のプログラミングしてる人いるか?
いません
一部を除いて普及しませんね
815 :
デフォルトの名無しさん:2007/07/16(月) 09:51:35
vc6.0を使用してダイアログベースのサーバーを作っています。
http://yonex1.cis.ibaraki.ac.jp/~yonekura/lecture03/lecture03d.html を参考にしながら作っていますが、
WSAAsyncSelect(sock, hWnd, uMsg, lEvent)
のhWndとはどのように取得すればいいのか、どうもよく分かりません。
また、ウィンドウにメッセージが送られた時の処理の書き方ですが、下記のような感じであってますか?
WndProcやDialogProcなど、調べたら似たようなものが多数出てきてパニクってしまいました。
(クライアントからconnectされた時に、ウィンドウにWM_USER+1のメッセージを送る)
WSAAsyncSelect(sock, hWnd, WM_USER + 1, FD_ACCEPT);
(メッセージマップ関数に↓を追加)
ON_MESSAGE(WM_USER + 1, OnCon)
(メッセージを受け取ったときの処理)
LRESULT CServerDlg::OnCon(WPARAM wParam, LPARAM lParam)
{
・・・
}
上記の記述で、クライアントからconnectされた時に、
OnCon関数を実行してくれるのでしょうか?
初歩的な質問かと思いますが、どなたか教えて頂けたら幸いです。
817 :
デフォルトの名無しさん:2007/07/16(月) 20:22:44
>>816 hWndはウィンドウハンドル
CreateWindowExの戻り値やFindWindowで取得した値を使えばいい。
>>812 最後にIPv6のコーディングをしたのは1998年です。
SocketAPIを使っている限りIPv4かIPv6かは気にしないで出来る
けど積極的に使ってもメリット少ないだけだからなあ
大きなデメリットも無いが
下手に対応すると「ウチの設定ではうごきません」
みたいなサポートに忙殺されそうなのでスルー
あとで対応できるように注意深くコーディングするけど
基本的にはナイショの機能扱いだな。
対応してくれって案件が来たら5分で実装完了100万円丸ゲット
が出来たらいいな って感じ
こういうのって学校や職場で最初に習わないのかなぁ?
824 :
810:2007/07/17(火) 15:46:12
>>815 ていうか 2年前ぐらいの技術だし 当時は今と逆で
P2Pって素晴らしいって風潮があったから議論する価値は
あったよ。リレーサーバーだとコストかかるし
今はP2P(UDP以外でも、UPnP使っても)というだけで過剰反応されるから閉じた環境でしか使いようがないと個人的には思ってる。
矛盾してるけど日曜プログラマの題材としては面白いと思う
もちろん名前の効いた大手がやるなら別だけど
最近 間にStorn(スペルあってる?)はさんだP2P手がけた・・・
stoneじゃないの?
>>824 第三者だが、815 の論点は UDP hole punching ならともかく、
より通りにくい TCP hole punching には意味がないってことじゃ
ないかと思うんだが
VCEE2005を使用してwinsock+IOCP?を勉強をしています。
google先生にお願いし、英語ながらサンプルを見つけサーバープログラムを
動かしたのですが、クライアントの接続を1度でも受け付けた場合
WSACleanupで例外(ヒープがどうのこうの)が発生して落ちてしまいます。
何故かデバッグモードのみで発生し、リリースモードでは発生しないので
ますます困惑しています。
WSACleanupで落ちる原因等、なにか解決の糸口になりそうなことを
ご存知の方がいたら是非教えてください。
ちなみにソースは
ttp://www.codeproject.com/internet/SimpleIOCPApp.asp の
multithreaded server using IOCP - 10.7 Kb
IOCP client - 7.1 Kb
を使用しました。
エラーメッセージがその通りなら
ネットワークとは関係ないところでバグってる可能性が高い。
おそらく、ヒープの管理ブロックを壊してる。
当方 Java1.5 で java.net.DatagramSocket を使用してUDPパケットをブロードキャストするプログラムを作っています
そこで質問なのですが、データグラムに載せるデータが1200〜1500バイトを超えると、DatagramSocket#send()が成功するにもかかわらず
100%の確率で受信側に到達しません(ローカル to ローカルでも100%ロスします)
まだパケットキャプチャはしていませんが、この状態で何か解決策を知っている方がおりましたら、解決策をお教え願えませんでしょうか?
UDPを何だと思ってるんだよ
>>830 >DatagramSocket#send()が成功するにもかかわらず
Javaは詳しくないんだけど、sendが成功値を返してきて、アプリが実行可能状態になっても、
それはあくまでアプリのバッファデータがTCPのバッファに全部コピーされ、アプリのバッファが
使用可能になりました・・程度の意味しかないんじゃ?
834 :
デフォルトの名無しさん:2007/07/18(水) 15:57:46
>>831 ユーザデータグラムプロトコルです
もとより信頼性が低いのは承知です
しかし高々2つのIPパケットに分割される程度ですむデータグラムも100%ロスはありえないと思って質問しました
>>832 そのようですね
あのあといろいろと実験してみたところ、
とりあえずプロトコルのバッファサイズは無関係で失敗するようでした
また一度インタフェイスまで降りて上がってくるようなブロードキャストが必ず失敗する
(キャプチャすると壊れたIPパケットを受信している)ようです
そう思ってローカルホストに送りつけたところ655xxバイトまでは正常に受信できました
…となると、の手打ちようが無い気がしてきました
フラグメントがうまくいってないみたいだね。
最近のプロトコルスタックはフラグメント化してくれないとかいう話も
どっかで見たような気がするけどどうなんだろう・・・
(そのOSでは)ブロードキャストパケットのフラグメント化はサポートされてないってことか?
>>834 UDPだぉ
UDPはフラグメントのサポートもへったくれもない。
そもそも1パケットサイズに入らないデータはサポートしてない。
>>836 んなこたーない。IPレベルでフラグメント化するので関係ない。
ただ、ブロードキャストがらみでおかしくなってるのかもね。
SO_BROADCASTたてるとDFも立つとか。
ユニキャストならうまく動くのか?というかOSはなによ?
>>836 8192 バイトの UDP パケットを用いる NFS プロトコルは
実装不可能な想像上の存在か?
840 :
830:2007/07/18(水) 19:26:32
IPパケットより大きいUDPデータグラムをとりあえず分解してくれているようですが
IPヘッダのチェックサムがイカれているっぽいです
Java5/with Windows XP Professional SP2
みなさんありがとうございます
軽いサンプルをうpしましたので、環境で試していただければ一発です
http://sourcepost.sytes.net/sourcepost/sourceview.aspx?source_id=29571 ちなみにこちらの環境では
C:\>java UDPTest 255.255.255.255
server start
client start
0bytes received
...
sent:46080 received:1024 loss:0.9777777777777777
C:\>java UDPTest
...
sent:46080 received:46080 loss:0.0
のような感じです
841 :
830:2007/07/18(水) 19:30:12
何回か実験したところ、上のようにネットワークブロードキャストしても
ちょっとだけ受信できる(再現性があいまい)ようになりました
かなり不明です。
カナリ実装依存なのでしょうか
842 :
830:2007/07/18(水) 19:31:02
...もしかしてBroadcastするときは専用のオプション設定しないとだめ?
843 :
827:2007/07/18(水) 19:55:47
レスどうもです。
>>828 そうするとWSACleanup内で処理されるはずの部分を
プログラム内で勝手にいじっちゃってるんでしょうか・・。
サンプルそのままでも起きるってことは環境の問題かな。
>>829 ご指摘ありがとう。
早速_beginthreadexに書き換えてみました・・がやっぱり駄目でした。
相変わらずWSACleanupで落ちてしまいます。
デバッグ時にしか起きないのでもう目をつぶってしまおうか、とも思うのですが
それじゃ勉強にならないし、どうにも気持ち悪い・・。
NICのchecksum offloadが悪さしてんじゃね?disableにしてみれ。
>>842 java.net.MulticastSocket 使うのはダメなんか?
>>840 ダメなのって 255.255.255.255 だけじゃね?
ホスト部だけ全ビット1にしたブロードキャストアドレスでやったら、そのまま動いたよ。
847 :
デフォルトの名無しさん:2007/07/18(水) 21:32:33
>>844 !!
ビンゴかもしれません
当方 Realtek RTL8139/810x を使用しているので checksum offload のON/OFFスイッチができませんが
そんな気がしてきました
ありがとうございます
>>845 IPマルチキャストは対応しているかどうかが怪しいのであまり使いたくなかったです
848 :
デフォルトの名無しさん:2007/07/18(水) 21:45:21
>>846 当方でも確認しました
参考にさせていただきます
851 :
デフォルトの名無しさん:2007/07/19(木) 13:02:05
winsock Controlを使ってVB6でUDPの画像送信プログラムを作っています
受信側でパケットキャプチャしたところパケットは届いているようなのですが
DataArrivalイベントが発生しないことがあり、精度が低いものになっています。
又、送信のループの中でSendDataの後にSleepを入れることで受信の精度が上がりました。
UDPとはこういうものなのでしょうか?
送信時にSleepを入れずに精度を上げたいと思うのですが
わかる方がいましたらよろしくお願いします
>>851 winsockコントロールはそういう使い方駄目
855 :
851:2007/07/19(木) 18:52:51
>>852 マルチキャストにしなきゃいけないものでして・・・
>>853 過去ログを見直してましたら同じような質問がありました・・・
失礼しました
すみません、質問させてください。
Cで組んだプログラムからミラーサーバ群にftpでアクセスし、そこからファイルをDLしてくる間の
TCPウィンドウサイズと輻輳ウィンドウサイズの変動を記録するようなものを作れと言われました。
TCPのウィンドウサイズはヘッダに書いてありますので、最悪あまり頭の良い方法ではないでしょうが
tcpdumpで通信監視してその結果から該当個所を引っこ抜いてくればいいかなぁと思っているのですが、
輻輳ウインドウサイズのほうはどうやって取得すればいいのか、ぐぐる先生にお尋ねしてもどうしてもわかりませんでした。
スロースタートや輻輳回避についてはそれなりに理解したつもりなのですが、結局どうすればいいのか見当が付かず、
困り果てている次第です。
どうぞお力をお貸し頂けますようよろしくお願い致します。
>>856 setsockopt + SO_DEBUG + trpt でOK??
858 :
デフォルトの名無しさん:2007/07/21(土) 22:00:31
ttp://www.nikkeibp.co.jp/news/flash/540166.html なお同社は19日、柏崎刈羽原発で記録した地震観測データを公開したが、
97台ある地震計のうち旧型の63台で、本震データが消失していたことも
明らかにした。通信回線が混雑しため、本震データを東京のサーバーに
転送する前に、地震計内部で余震データに書き換わってしまったという。
3月の能登半島地震の際も北陸電力の志賀原発で同様の事象が発生していた
ため、東電では2008年度までにすべての地震計を新型に更新する予定だった。
>>857 返信、どうもありがとうございます。
すみません、私物凄く肝心なことを記載し忘れていました・・・。
実はftpのクライアントを自分で書くだけの力はないものでして、
popenを使ってftpを呼び出して使っています・・すみません。
setsockopt + SO_DEBUG + trptではどうかとのことですが、
これはPCBの情報を参照しろという意味合いでしょうか。
setsockoptを使いたければ自分でsocket()でソケットを生成しなければならない、
つまりソケットプログラミングの知識は必須ということですかねぇ・・。
折角お教えいただいたのに、今の私では生かすことが出来そうにありません。
本当に申し訳ありません。
861 :
デフォルトの名無しさん:2007/07/22(日) 00:39:29
WSAGetLastError() が、997という値を返したのだが、
これって、どうゆうエラー???
だいたいWSAのエラーのベース値が、10000なんだが。
全角数字ってキモイよな
865 :
デフォルトの名無しさん:2007/07/22(日) 01:47:19
>>864 あらら。初歩的ミスでスマソ。
ベース値が10000なんでWSAのつくエラーはぜんぶ1万以上と思ってました。
866 :
デフォルトの名無しさん:2007/07/22(日) 01:55:09
しかもエラー値チェックのすぐあとで、重複用にWSA_IO_PENDINGと比較してるし
TCPプログラミングのセオリーとは?
UDPのソケットプログラムしか書いたことがないのですが、
今回信頼性確保のためTCPを使うことになりました。
TCPでのパケット受信ではreadやrecvを使いますが
一度で全てのデータを取得できるとは限らないので
例えば、以下のようにループ処理で読むのが鉄則だと読んだのですが、
for( ; ; )
{
recv(....)
if(ループを抜ける条件) break;
}
例えば100バイト読んだらループを抜けるという条件を設定した場合
何バイト送られてくるか分からないデータはどのように読めばいいのでしょうか?
(可変長の構造体データを読みたい。受信側では何バイト送られてくるか
予測できない)
アプリ(TCPよりも上位の層)でデータの終端を示すマーカーみたいなものを
決めて、1バイトずつ調べてマーカーが現れたらループを抜けるという風にす
べきなのでしょうか?
そもそもTCPはバイトストリームなので1バイトずつチェックしながら読むのが
定石なのでしょうか?
UDPならrecvfromを一度呼び出せば、ある構造のデータ
を全て読み出せるのでこのようなことを考えなくてよいのですが。
「勝手な仮定」さえしなければ
別にどんなやり方でも良いと思うけど
強いて言えばHTTPライクに柔軟に対応するのが無難かと。
869 :
デフォルトの名無しさん:2007/07/22(日) 11:35:57
>>860 輻輳ウィンドウの値は、TCP/IPスタックの内部変数にしかすぎないので、
いくらキャプチャしても直接はそんな情報は出てこない。
ただし、サーバとクライアントのネットワークの間になんらかのしかけで
遅延が入るようにしておいて、パケットの送り側が一度にいくつのセグメント
を送信するかをモニターすることで、多少は予想できる・・・・カモ
何バイト送られてくるかわからないのに
100バイトでループを抜けようと考えた根拠を知りたい
宇宙を構成する単位が100バイトだからです
てっきり42バイトかと
何ビットあるか判らないものを単位にするとは
宇宙も大したことないな。
ビット単位じゃなくてクォビット単位だったら話は分かる
レスありがとうございました。
>>870 特に100という数字に意味はないです。
例えばです。
>>868 ストリーム志向ということで柔軟に対応します。
プロトコル設計次第だけど
固定長
固定長ヘッダにサイズをのせる。
ターミネート文字を指定する( CR+LFとか)
のあたり
人生、宇宙、すべての答え
42歳
880 :
デフォルトの名無しさん:2007/07/22(日) 21:00:06
>一度で全てのデータを取得できるとは限らないので
>例えば、以下のようにループ処理で読むのが鉄則だと読んだのですが、
それが正解だけど
なぜか世間ではfdopenなどを通してFILE*にいれて
fprintfで出力など、結構いい加減にやってる。
実はデータ量少ない時は気にしなくてもいいのかも。
>>882 「なぜか」じゃないよ、ちゃんと理由があってのことだ。
stdioは「必要なだけループ」をやってくれるから、それでいい場合は
お任せにしまっているだけ。
例えばread()やrecv()は要求したバイト数未満で制御を戻す場合が普通にあるが
fread()はそれに達するまで繰り返しread()を呼んで粘る。
fgets()なども同様で、改行が来るかバッファがフルになるまで粘る。
ただ、stdioはブロッキングかつバッファリングを行うから、
細かい制御が必要な場合には向かないし、select()などとの相性も悪い。
「一般的にユーザがやるだろうこと」を 肩代わりしてくれるのが
標準ライブラリのお仕事だからね。
885 :
860:2007/07/23(月) 00:55:30
>>869 レスありがとうございます。遅くなってしまってすみません。
輻輳ウィンドウの値は、おっしゃる通り送信側の内部変数ですから、
普通に考えれば受信側から参照は出来ませんよね・・。
確かにセグメントを監視することで、送信側が採用している輻輳制御の方法と、
その値はある程度予想はつくかもしれません。
(というか私もそれしか思いつきませんでした・・。)
けれども、そのためには当然通信効率の犠牲と、ある程度の時間、
ある程度のパケット量が必要になるので、実用性はどうかと問われたら
厳しいかなぁと考えています。
折角考えていただいたのにすみません・・・。
もし、輻輳ウィンドウのサイズではなく、輻輳が起こったかどうかであれば、
受信側から把握することは出来るのでしょうか。
もしご存知でしたら、ご回答いただけると幸いです。
>>882 「いい加減」かどうかは状況によるじゃん。
行志向のデータじゃないのに、
setvbuf(..., _IOLBF, ...)になってたら問題。
ところでfprintfが問題になる状況ってどんな時ですか?
>>886 fprintfってたしか改行でバッファフラッシュしなかったっけ。
もしそうなら NW でこれをやると効率がガクンと落ちる。
レスありがとうございます。
>>877 固定長ヘッダにサイズをのせて、二段階で受信するように
します。
1回目のrecv処理 固定長ヘッダを受信
2回目のrecv処理 ヘッダのサイズ値分だけ受信
>>882 作法としてはセオリーに従うべきだと思いますので(万が一の
こともありますから)、常にループ処理にします。
>>888 >1回目のrecv処理 固定長ヘッダを受信
ちょっとずつ読むのは帯域の無駄遣い的には最悪だから
そういうのを気にする用途では注意してね。
>>889 数秒おきに来るコマンドに応答を返すだけなので
今回は大丈夫かと思います。
ありがとうございました。
>889
silly window syndromeのことをいってるの?
893 :
デフォルトの名無しさん:2007/07/23(月) 23:56:28
>>885 輻輳というと意味が広すぎるけど大きくは
1. パケットロス
2. パケット遅延
3. パケット重複
くらいかな、パッと思いつく限り。
で、パケットロスに関してだけいえば、高速再転送アルゴリズム(RFC 2581, 2582)
あたりが動作しているかどうかは、受信側のDUPACKと送信側の挙動見れば判別
つくんじゃないかな。SACKとか、その他もろもろのアルゴリズムもからんでくる
こともあるが・・・。
パケット重複も、キャプチャみればなんとか。
パケット遅延はこれまたプロトコルスタックの内部変数に依存する。
再送間隔の変化を地道にモニタリングするとか・・・。
895 :
885:2007/07/26(木) 03:13:54
>>893 ご丁寧にありがとうございました。
相変わらずレスが遅くて申し訳ないです。
確かに、輻輳とだけいうと意味が広いですね、すみません・・。
(とても曖昧な質問だったのにご丁寧に回答を頂き、本当にありがとうございます)
パケットロスに関しては、色々なアルゴリズムが絡んでくるとなると難しいですね・・。
送信側から把握するというのであれば比較的簡単ですが、今回は受信側から、ですからねぇ。
パケットの重複は、おっしゃる通りパケットの特定フィールドを監視すればなんとかなりますね。
これは私みたいなのでも比較的簡単に実装できそうです。
パケットの遅延も内部変数依存ですか・・、困りました。
何か良い方法ないかなぁと探していたところ、一応それっぽいものを見つけました。
長谷川洋平・下西英之・村瀬勉
「TCPトラヒックの解析による端末/ネットワーク通信ボトルネック判定手法」
NECシステムプラットフォーム研究所
(
http://www.itrc.net/report/meet17/shiryo/22A/hasegawa.pdf)
によると、RTTが増加し、且つThroughputがほぼ一定である場合、
自トラヒックが原因となる遅延が増加し、RTTが増加し、Throughputが減少した場合、
他トラヒックが原因となる遅延が増加したと判断できるとのことです。
但し、判別精度は凡そ70%弱だそうですけれど。
明示的に輻輳の通知でもしない限り、ネットワークの輻輳検知はそもそも難しいはずなので、
この70%に重複も考慮する辺りで妥協してもいいのかなぁと思わなくもありません。
地道にモニタリングする気力と根性と、そして一番肝心な時間がなさそうですごめんなさいorz
教えていただいた内容と、自分で調べた内容を踏まえて、再度教授に相談してみようと思います。
本当にどうもありがとうございましたm(_ _)m
torahikku
898 :
デフォルトの名無しさん:2007/07/27(金) 03:24:34
伝統的に
「トラフィック」ではなく
「トラヒック」という言葉を
使うらしい
〇∧〃 でもそんなの関係ねぇ!
/ ) そんなの関係ねぇ!
< \
○/
∨) はい、オッパッピ〜
/ |
コンピュータ用語(プログラミング技術者の用語)として
伝統的に「ナルポ」ではなく「ヌルポ」という言葉を使うらしいよ。
URL略 あたりで確かめてごらん。
デバッグ用語(技術奴隷の用語)として
伝統的に「ウォーニング」ではなく「ワーニング」という言葉を使うらしいよ。
URL略 あたりで確かめてごらん。
どこの言葉か忘れたけどチャンネルをチャネル
チャヌー
「トラヒック」はネットワーク技術者用語ってより、元NTT用語。
通信業界歴の長い人はトラヒックで、新しい人はトラフィックだったりするけど、
同じ人でも場の空気読んでトラヒックとトラフィックを使い分けたりするんで、
このトラヒックとトラフィックのニュアンスの違いを言葉で表現するのは難しい。
言葉を使う場面(聴衆の前でのプレゼン、社内、社外との打ち合わせ、など)、
その言葉で表す事象、でてくる装置などによって、
「トラヒック」と「トラフィック」を適切に使い分けることができるようになったら一人前の通信業界人とも言える。
>>899-900 それは英語の発音とカタカナ表記の問題だろ。routerをカタカナでラウターって書く奴なんて見たこと無い。
エヌテーテー
アイロンとアイアンだな
ネットワークではないがDB用語のクエリーもそうだな。
IBMではキューリーなので使い分けが必要。
WindowsXPだけど、
1. NICを2枚差す
2. 同一プログラム内で一つのNICを送信専用、もう一つを受信専用にする
3. 送信側からパケットを投げて、受信側でいくつ受信したかをカウント
4. 送信数と受信数の差分から、通信経路上でいくつパケロスしたか
って感じのプログラムを作りたいんだけど、
そもそも2で躓いた orz
複数NICのうち、任意のNICを割り当てるのってどうするの?
どこかの資料のポインタとか教えてください
>>907 は、次に、
>3. 送信側からパケットを投げて、受信側でいくつ受信したかをカウント
で、パケットが外に飛ばないところで躓くと予想。
パケット投げるとき、宛先アドレスが自ホストのアドレスだと、NICドライバにたどり着く前に
カーネル内で折り返される。
パケットソケットでEthernetフレーム組み立てて書き込め。
910 :
907:2007/07/27(金) 18:02:58
>>908 ありがとうございます!
>>909 うわ、それは全然気づきませんでした・・・
ありがとうございます!
恐れ巣だが
デスクトップ を ディスクトップ
インタープリター を インタープリンター
というお偉いさんがこの業界にいる
お偉いさんだけに誰にも指摘されない
昔のIT業界は、例え外資であっても英語の発音を知らない奴が多かったんだな。
プロバイダー を プロバイザー と言ってるおエロいさんが
えへ
そろそろマ板いけ
え、この人結構すごいと思ってたのにショックだわー
本もってるw
ディスクトップは聞いててイライラする。
オレもオレも!<ディスクトップ
昔から思ってた。
意味が通らないからイライラすんだよな。
どうしてそう勘違い出来るのかと。
「円盤上」かえ!?
ぐぐると結構出てくるんだよなぁ…。企業サイトでも。
921 :
デフォルトの名無しさん:2007/07/28(土) 08:16:23
雨が降っても選挙行こうな!!
自分の選挙区に道路とか空港とか利益誘導ばっかり
主張するやつには投票するなよ。
世襲議員、2世議員は投票するなよ
選挙前に限って「弱者のための政治」というやつには気をつけろ!自民党のベテラン議員に多い!
委員会で質問しないようなやつには投票するなよ
業界団体の利益ばかり主張するやつに投票するなよ
ホームレスとかネットカフェ難民、介護難民問題を
取り上げる「弱者のため」の議員を探そう!!
自分の選挙区に道路とか空港とか利益誘導はしてもいいと思う
それ以外は同意
電話で○○党の議員に投票よろしくと逝って来る香具師には投票したくなくなる漏れ
コピペに釣られるなバカども
>ネットカフェ難民
24時間運営の店を取り締まるべきだな
こいつらのせいで治安が悪化してる
客も入れる店も同罪
こういう奴等は終いに徒党を組んで強盗団になるぞ
>>907 それって、行きと帰りで通信経路違うの?
それとも送受信パケットをカウントしたいだけ?
カウントしたいだけなら、WindumpやWinpcap使えばいいだけと違うの?
直接mmapとか使ってバッファに直書きする方法の
サンプルどっかにおちてなーい?
928 :
デフォルトの名無しさん:2007/07/31(火) 03:14:29
> 「TCPトラヒックの解析による端末/ネットワーク通信ボトルネック判定手法」
> NECシステムプラットフォーム研究所
> (
http://www.itrc.net/report/meet17/shiryo/22A/hasegawa.pdf)
URLが見つからなくなってたんだけど
> によると、RTTが増加し、且つThroughputがほぼ一定である場合、
> 自トラヒックが原因となる遅延が増加し、RTTが増加し、Throughputが減少した場合、
> 他トラヒックが原因となる遅延が増加したと判断できるとのことです。
うーん。論文読んでないのでなんともいえないが、上記読む限り条件限定しすぎてる
し、これだけ制限して70%弱の判別精度じゃ役に立たない気がする。RTTのみに着眼し
て評価することで、マクロ的な輻輳の挙動が評価できるという発想は面白いが。失敗
してる気がする。
トラヒックって何か腹筋が引きつる感じだな
正確にはトレフィックだがな
932 :
デフォルトの名無しさん:2007/07/31(火) 13:55:29
ソケットディスクリプタをfdopenしてもいいんだっけ?
>>932 問題なし。ただしfflushには気を使え。
934 :
932:2007/07/31(火) 14:02:08
やっちゃった・・・
fdopenしてfgetsするとタイムアウトが設定できないね
ブロックするかしないかの2択しかないや
alarm(2)
937 :
デフォルトの名無しさん:2007/08/01(水) 15:30:57
ルータ越えの問題の質問なんですが、
仮にAがサーバとなりB,Cがそこに接続後、BとCが直接通信を行うとする場合で
Aはもちろんルータのポートが開いてて外部から接続可能で
B,Cについてはルータの設定などしていなく外部からの接続は出来ない場合
B,CからAに接続する事は可能ですけどB,Cに接続する事は基本的に無理ですよね。
B,CがListenしてサーバー機能が有ったとしてもルータで弾かれますので。
そこで、BがAに接続するとAと通信する為Bに適当なポートが開きますよね。
そのポートをBがListenし、CがAに接続した時、AがCにBのアドレスとそのポートを教え
CはBのそのポートにアクセスすする事でルータ越え出来るんじゃないかと思ったわけですが
実際そういう事は可能でしょうか。
>>937 UDP hole punching で検索してみるといい。
939 :
デフォルトの名無しさん:2007/08/01(水) 16:28:15
「接続」と書いているが、
ファイヤーウォールは接続を追い掛けているので、TCPでは無理だよん。
# SYN, FINを見て
941 :
デフォルトの名無しさん:2007/08/01(水) 22:41:16
>>937 B(Port 100) <-> A (Port 500)
ファイアウォールうんぬん以前に。上記のように接続が確立している時に(IPアドレ
スは、ルータからむし省略)、BでPort100をListenすることがそもそもできない。ポー
ト番号が使用中だから。
ムーンムームでーす
>>941 httpd は 80 番ポートでたくさんコネクション張ってるわけだが。
実際は TCB で管理されるから
{ local-IP, local-port, remote-IP, remote-port }
でユニークならいい(確かリチャードの本に書いてあったはず)。
945 :
デフォルトの名無しさん:2007/08/02(木) 22:44:41
>>944 >{ local-IP, local-port, remote-IP, remote-port }
>
>でユニークならいい(確かリチャードの本に書いてあったはず)。
いや、そうだけどさ。Listenするときはまだ接続確立うんぬん
以前の話だから。使用中のポートは、Listenできん。たとえREUSEADDR
つけようが。
そんなもん接続切れば良いじゃないか。
そうか、がんばれ。
948 :
デフォルトの名無しさん:2007/08/03(金) 02:06:56
>>946 無知が罪とはいわん。だが、もう少し恥を知ったほうがいい。
分かってないなぁ。
>937の話を理解してないだろ。
それが問題で無理というのは違うと言う事だ。
( ゚д゚)ポカーン
病んでるなぁ
思いて学ばざれば、ってやつだな
Cでreadやwriteのタイムアウトは設定できるようになったけど
connectのタイムアウトはどうやったら設定できる?
select使うのは無しの方向で
じゃあpoll.
じゃあalarm
selectもpollもalarmも無しの方向で
なんでselectやらを使っちゃいけないわけ?
selectに飽きたから じゃあ駄目かな
alarmはスレッドに弱いしpollはどうでもいいし
それにいろんな方法知っといた方が 楽しいじゃん
お前の酔狂につきあう義理は無いな
epollで
kqueueも
知りたいだけならそれこそ自分で調べ上げたほうが楽しいと思うけどな
そろそろsocketに飽きてきたんだけどなんかいいのない?
いつの間にやら次スレはPort 20か。
この辺はFTPやらSSHあたりが並んでる。
スレタイに入れてみるのはどうでしょ?
jacket
ネトゲ用にリアルタイム性のあるプロトコルを探してるんだけど
javaのrtp(かリアルタイム用のプロトコル)の実装物しらない?
とりあえずjava.net.RTPとか入れてみたけどクラスパス通しても実行できないんだ
iSCSI(笑