- ベストアンサー
UDP処理のエラーについて
- UDP処理中にエラーが発生する原因として、ポートのバッファが限界に達したことが考えられます。
- このエラーは、システムのバッファ領域が不足しているか、キューがいっぱいであることが原因となっています。
- エラーを解決するには、バッファサイズを拡張するか、キューサイズを調整する必要があります。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
> 一度Sendした場合、受信待ち状態が解除されるので、 > 再度BeginReceiveを呼び出しています。 元々コールバック関数中でBeginReceiveを呼び出しておらず, その場合には一度だけコールバック関数が呼ばれるために, Sendで受信待ち状態が解除されると勘違いした,ということはないですか。 UdpClient.Sendはsendto WinSock2 APIを呼び出すのですが, このAPIはRecvFrom WinSock2 APIによるoverlapped I/Oを阻害しません。 わかりにくいなら,受信用のソケットと送信用のソケットを分離してしまうのも一つの方法だと思います。
その他の回答 (3)
- Yune-Kichi
- ベストアンサー率74% (465/626)
> lUdpClient.udp.BeginReceive(New System.AsyncCallback(AddressOf receivecallback), lUdpClient) #ここでエラー ここは送信処理を行うのではないのですか? どう見ても受信処理をさせようとしていますが。 実際に送信するつもりでBeginReceiveしていれば, タイマーでBeginReceiveの呼び出しが蓄積していきますから例外が発生します。
お礼
ご回答ありがとうございます。 申し訳ありません。ソースが足りませんでした。 以下のように送信処理を行っています。 ' リモートホストを指定してデータを送信 lUdpClient.udp.Send(sendBytes, sendBytes.Length, remoteHost, remotePort) lUdpClient.udp.BeginReceive(New System.AsyncCallback(AddressOf receivecallback), lUdpClient) #ここでエラー 一度Sendした場合、受信待ち状態が解除されるので、 再度BeginReceiveを呼び出しています。 やはり送信処理中にBeginReceiveを使用しているのが原因なのでしょうか。 しかし、受信待ち状態にするにはこの方法しかないと思い、 仕方なくBeginReceiveを使用しています。
- Yune-Kichi
- ベストアンサー率74% (465/626)
大量にUdpClientでBeginReceiveさせ例外を起こさせたところ,どうもOS側のキューが不足しているようです。 # 手元の環境のソースだと,Socket.csの4967行目。 なので,ThreadPoolは関係ありませんでした。 WSARecvFrom APIのエラーにもWSAENOBUFSはないので,通常は起こらないと見られているのでしょう。 確実な解決策は,overlapped I/Oの数を減らすことしかないと思います。 まず,BeginReceiveをそれだけたくさん行う必要があるのでしょうか。 例えば,最大で3個程度作るだけにしてしまえば,この例外が起きることはなくなると思います。 # 20件/secであればこれでさばけると思いますが。
お礼
ご回答ありがとうございます。 送信処理はTimer、受信処理はBeginReceiveを使用しているのですが、 うまくいきません。 Private Sub SocketsReception() ' 変数宣言 lUdpClient = New UDPState() lUdpClient.netPoint = New Net.IPEndPoint(Net.IPAddress.Any, iLocalPort) lUdpClient.udp = New Net.Sockets.UdpClient(lUdpClient.netPoint) ' 受信処理開始 lUdpClient.udp.BeginReceive(New System.AsyncCallback(AddressOf receivecallback), lUdpClient) End Sub Public Sub receivecallback(ByVal AR As IAsyncResult) Try Dim ClientData As UDPState = New UDPState() Dim LU As Net.Sockets.UdpClient = CType(AR.AsyncState, UDPState).udp Dim LE As Net.IPEndPoint = CType(AR.AsyncState, UDPState).netPoint Dim receiveBytes As Byte() = LU.EndReceive(AR, LE) Dim receiveString As String = enc.GetString(receiveBytes) Dim receiveAddress As System.Net.IPAddress = LE.Address '---受信処理を行う--- lUdpClient.udp.BeginReceive(New System.AsyncCallback(AddressOf receivecallback), lUdpClient) ' データ異常の場合 Catch ex As System.Net.Sockets.SocketException ' 終了処理 Catch ex As Exception End Try End Sub Private Sub Timer2_Tick(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Timer2.Tick '---送信処理を行う--- lUdpClient.udp.BeginReceive(New System.AsyncCallback(AddressOf receivecallback), lUdpClient) #ここでエラー ' 送信エラー Catch ex As System.Net.Sockets.SocketException ' 終了処理 lUdpClient.udp.Close() SocketsReception() End Try bSendOn = False End Sub
- Yune-Kichi
- ベストアンサー率74% (465/626)
えーっと,OSが認識するプロセッサの個数 (タスクマネージャのパフォーマンスタブのCPUの個数) はいくつですか。 これが3以下であれば,3001個もスレッドを非同期I/Oを同時に実行することはできません。 # 4以上でも,3001個も非同期I/Oを作るのが良いとは言えませんが。 可能であるならば,そもそもBeginReceiveの回数を減らし,コールバック関数で再度BeginReceiveするなどしてみてはどうでしょうか。
お礼
ご回答ありがとうございます。 デュアルコアですので2つになります。 >可能であるならば,そもそもBeginReceiveの回数を減らし,コールバック関数で再度BeginReceiveするなどしてみてはどうでしょうか。 コールバック関数で再度BeginReceiveを実行したところ1時間ほどで同じ下記エラーが発生しました。 1秒間に20回くらいUDPでデータを受信しているため、パケットの量が多すぎてエラーになったのでしょうか。 システムのバッファ領域が不足しているか、またはキューがいっぱいなため、ソケット操作を実行できませんでした。
お礼
大変申し訳ありません。 ご指摘の通り、BeginReceiveの認識に誤りがありました。 コールバック関数中でBeginReceiveは呼び出していたのですが、 送信処理でもBeginReceiveを呼び出していました。 Sendを実行すると受信待ちが解除されるのだと思っていました。 送信処理にあるBeginReceiveを削除したところ、正常に動作するようになりました。 いつも1時間で落ちていたのに4時間経っても問題ありません。 ありがとうございました。