• ベストアンサー

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

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

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

  • ベストアンサー
  • tanma3
  • ベストアンサー率58% (14/24)
回答No.3

#2 >tanma3様、お手数ですが、もうしばらく >お付き合い頂けないでしょうか? そうですね、ちょっと検証してみましょう。 ということで、自宅環境(vc++6.0 + winsock2.0)にて簡易同期UDP処理を作成して検証した結果やはり"alp_tomy"さんのご報告どおりでした。 まあ、当然ですが。。。 ということで、以下こちら環境で検証した結果の詳細です。 sendtoは正常終了しているので、やはり送信処理に数秒かかってると仮定するのが妥当だと思います。 但し時間がかかってるのは送信処理ではなく同期用処理ではないかと仮定してみました。 (自宅に詳細資料がないので、あくまでも仮定ですが。。。) そこでselectに代わる非同期用APIである"WSAAsyncSelect()"を使用してみたところ、感覚的にはwaitなしにsendtoからreturnしてきているようです。 但し上記APIは登録ウインドウに対しメッセージを送信するAPIですので、メッセージ処理はwindow procで実施しなければならないので、少し処理が複雑になるかと思います。 ということで、大雑把で申し訳ありませんが、一度"WSAAsyncSelect()"で試してみてください。 また、そこまでしなくてもいいというようなレベルの問題であれば、非同期化とは別の解決策も存在すると思いますので、別角度からのアプローチも有効かと思います。

alp_tomy
質問者

補足

tanma3様、お休みのところ(?)ありがとうございました。 >但し時間がかかってるのは送信処理ではなく同期用処理ではないかと仮定してみました。 tanma3様のこの言葉から調査して以下を試してみました。。。 unsigned long arg = 1L; ioctlsocket(sock,FIONBIO,&arg) (Winsockで非ブロッキングの設定をするための関数のようです。) 、、、で一応こちらが期待する結果は得られたのですが、 対策として間違っていないでしょうか??? >"WSAAsyncSelect()" 、、、に関しましては今回画面系のアプリではないため、 未確認なのですが、次回画面系アプリ開発の際には是非使用したいと 思います。 以上、お手数ですが宜しくお願い申し上げます。

その他の回答 (3)

  • tanma3
  • ベストアンサー率58% (14/24)
回答No.4

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

alp_tomy
質問者

お礼

tanma3様、お付き合いありがとうございました。。。 >間違ってないと思いますよ。 安心しました。。。(自分はsocket初心者なもので、、、) おかげで無事解決できました。 また何かご縁がありましたら是非是非、 宜しくお願い申し上げます。。。

  • tanma3
  • ベストアンサー率58% (14/24)
回答No.2

#1ですが、 まったく問題ないです。 問題があるのは私のコメントのほうですorz 何を寝ぼけていたのか、sendtoは投げっぱなし用関数なのに。。。 ということで、"3秒ぐらい応答が帰ってこない。"という問題についてですが、エラーが出ていないのであれば、sendtoが3秒間処理中であると考えるのが妥当かとも思うのですが、何か大きいサイズのデータを転送していますか?

alp_tomy
質問者

補足

tanma3様、ご回答ありがとうございます。 >問題があるのは私のコメントのほうですorz >何を寝ぼけていたのか、sendtoは投げっぱなし用関数なのに。。。 いえいえ。。。 こちらも良い勉強になりました。 >何か大きいサイズのデータを転送していますか? 送信してるサイズは1400バイト弱です。 メッセージのサイズが原因でしょうか? (ちなみに、LAN接続時は100ミリ秒もかからずに  送信できています。) tanma3様、お手数ですが、もうしばらく お付き合い頂けないでしょうか?

  • tanma3
  • ベストアンサー率58% (14/24)
回答No.1

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

alp_tomy
質問者

補足

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,...);(送信処理) } } } ------------------------------------------

関連するQ&A