こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

Winsockのsendto関数のタイムアウトについて

はじめまして。。。
Winsockのsendto関数を使用してユニキャストでUDP送信
しているのですが、LAN切断時等送信先がない場合、
3秒くらいsendto関数の応答が帰ってこなくて困っています。
setsockoptの「SO_SNDTIMEO」で送信タイムアウトを
設定してみたのですが、状況は変わりませんでした。
もし、LAN切断時でもすぐに応答が帰ってくる方法が
ございましたらご教示頂けないでしょうか?

環境
OS:Windows XP
言語:.NET 2003 C++

投稿日時 - 2008-07-17 19:45:58

QNo.4184217

すぐに回答ほしいです

質問者が選んだベストアンサー

#2
>tanma3様、お手数ですが、もうしばらく
>お付き合い頂けないでしょうか?
そうですね、ちょっと検証してみましょう。

ということで、自宅環境(vc++6.0 + winsock2.0)にて簡易同期UDP処理を作成して検証した結果やはり"alp_tomy"さんのご報告どおりでした。
まあ、当然ですが。。。

ということで、以下こちら環境で検証した結果の詳細です。
sendtoは正常終了しているので、やはり送信処理に数秒かかってると仮定するのが妥当だと思います。
但し時間がかかってるのは送信処理ではなく同期用処理ではないかと仮定してみました。
(自宅に詳細資料がないので、あくまでも仮定ですが。。。)
そこでselectに代わる非同期用APIである"WSAAsyncSelect()"を使用してみたところ、感覚的にはwaitなしにsendtoからreturnしてきているようです。
但し上記APIは登録ウインドウに対しメッセージを送信するAPIですので、メッセージ処理はwindow procで実施しなければならないので、少し処理が複雑になるかと思います。

ということで、大雑把で申し訳ありませんが、一度"WSAAsyncSelect()"で試してみてください。

また、そこまでしなくてもいいというようなレベルの問題であれば、非同期化とは別の解決策も存在すると思いますので、別角度からのアプローチも有効かと思います。

投稿日時 - 2008-07-20 22:07:19

補足

tanma3様、お休みのところ(?)ありがとうございました。

>但し時間がかかってるのは送信処理ではなく同期用処理ではないかと仮定してみました。
tanma3様のこの言葉から調査して以下を試してみました。。。

unsigned long arg = 1L;
ioctlsocket(sock,FIONBIO,&arg)
(Winsockで非ブロッキングの設定をするための関数のようです。)

、、、で一応こちらが期待する結果は得られたのですが、
対策として間違っていないでしょうか???

>"WSAAsyncSelect()"
、、、に関しましては今回画面系のアプリではないため、
未確認なのですが、次回画面系アプリ開発の際には是非使用したいと
思います。
以上、お手数ですが宜しくお願い申し上げます。

投稿日時 - 2008-07-21 10:07:30

ANo.3

このQ&Aは役に立ちましたか?

18人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.4

#3
>、、、で一応こちらが期待する結果は得られたのですが、
>対策として間違っていないでしょうか???
間違ってないと思いますよ。むしろ提案させていただいたAPIより良いと思います。
用はnonbroking modeで利用できればいいだけですので。
※すみませんvcと聞いた時点でウインドウがあると勘違いしてしまいまして...orz

解決おめでとうございます。

投稿日時 - 2008-07-21 17:53:54

お礼

tanma3様、お付き合いありがとうございました。。。

>間違ってないと思いますよ。
安心しました。。。(自分はsocket初心者なもので、、、)

おかげで無事解決できました。
また何かご縁がありましたら是非是非、
宜しくお願い申し上げます。。。

投稿日時 - 2008-07-21 19:19:32

ANo.2

#1ですが、
まったく問題ないです。
問題があるのは私のコメントのほうですorz
何を寝ぼけていたのか、sendtoは投げっぱなし用関数なのに。。。

ということで、"3秒ぐらい応答が帰ってこない。"という問題についてですが、エラーが出ていないのであれば、sendtoが3秒間処理中であると考えるのが妥当かとも思うのですが、何か大きいサイズのデータを転送していますか?

投稿日時 - 2008-07-18 23:39:58

補足

tanma3様、ご回答ありがとうございます。

>問題があるのは私のコメントのほうですorz
>何を寝ぼけていたのか、sendtoは投げっぱなし用関数なのに。。。
いえいえ。。。
こちらも良い勉強になりました。

>何か大きいサイズのデータを転送していますか?
送信してるサイズは1400バイト弱です。
メッセージのサイズが原因でしょうか?
(ちなみに、LAN接続時は100ミリ秒もかからずに
 送信できています。)

tanma3様、お手数ですが、もうしばらく
お付き合い頂けないでしょうか?

投稿日時 - 2008-07-19 22:41:54

ANo.1

setsockoptではなくselectでタイムアウト0としてnon-brocking、モードにしてみてはいかがですか?

投稿日時 - 2008-07-18 00:18:49

補足

tanma3様、早速のご回答ありがとうございました。
下記のソースコードで確認してみたのですが、
結果変わらずでした×××
ソースがまずいのでしょうか?
お手数ですが、宜しく御願い申し上げます。
------------------------------------------
while(1){
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
fd_set wrds;
FD_ZERO(&wfds);
FD_SET(sock, &wfds);
int n = select(sock +1, NULL, &wfds, NULL, &timeout);
if(n > 0){
if(FD_ISSET(sock, &wfds)) {
sendto( sock,...);(送信処理)
}
}
}
------------------------------------------

投稿日時 - 2008-07-18 11:34:08

あなたにオススメの質問