疑問に思ったので教えて下さい。
以下のようにBeginReceive処理を複数回行うとエラーが発生します。
これは1つのポートにおけるバッファが限界に達したためなのでしょうか。
' 変数宣言
lUdpClient = New UDPState()
lUdpClient.netPoint = New Net.IPEndPoint(Net.IPAddress.Any, iLocalPort)
lUdpClient.udp = New Net.Sockets.UdpClient(lUdpClient.netPoint)
For i = 0 To 3000
lUdpClient.udp.BeginReceive(AddressOf SendData, lUdpClient)
Next
システムのバッファ領域が不足しているか、またはキューがいっぱいなため、ソケット操作を実行できませんでした。
No.1
- 回答日時:
えーっと,OSが認識するプロセッサの個数 (タスクマネージャのパフォーマンスタブのCPUの個数) はいくつですか。
これが3以下であれば,3001個もスレッドを非同期I/Oを同時に実行することはできません。
# 4以上でも,3001個も非同期I/Oを作るのが良いとは言えませんが。
可能であるならば,そもそもBeginReceiveの回数を減らし,コールバック関数で再度BeginReceiveするなどしてみてはどうでしょうか。
参考URL:http://msdn.microsoft.com/ja-jp/library/system.t …
ご回答ありがとうございます。
デュアルコアですので2つになります。
>可能であるならば,そもそもBeginReceiveの回数を減らし,コールバック関数で再度BeginReceiveするなどしてみてはどうでしょうか。
コールバック関数で再度BeginReceiveを実行したところ1時間ほどで同じ下記エラーが発生しました。
1秒間に20回くらいUDPでデータを受信しているため、パケットの量が多すぎてエラーになったのでしょうか。
システムのバッファ領域が不足しているか、またはキューがいっぱいなため、ソケット操作を実行できませんでした。
No.2
- 回答日時:
大量に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
No.3
- 回答日時:
> 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を使用しています。
No.4ベストアンサー
- 回答日時:
> 一度Sendした場合、受信待ち状態が解除されるので、
> 再度BeginReceiveを呼び出しています。
元々コールバック関数中でBeginReceiveを呼び出しておらず,
その場合には一度だけコールバック関数が呼ばれるために,
Sendで受信待ち状態が解除されると勘違いした,ということはないですか。
UdpClient.Sendはsendto WinSock2 APIを呼び出すのですが,
このAPIはRecvFrom WinSock2 APIによるoverlapped I/Oを阻害しません。
わかりにくいなら,受信用のソケットと送信用のソケットを分離してしまうのも一つの方法だと思います。
大変申し訳ありません。
ご指摘の通り、BeginReceiveの認識に誤りがありました。
コールバック関数中でBeginReceiveは呼び出していたのですが、
送信処理でもBeginReceiveを呼び出していました。
Sendを実行すると受信待ちが解除されるのだと思っていました。
送信処理にあるBeginReceiveを削除したところ、正常に動作するようになりました。
いつも1時間で落ちていたのに4時間経っても問題ありません。
ありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) 実行時エラー´5854´ 文字列型パラメーターが長すぎます。 3 2023/06/08 21:17
- 英語 "by a ~ 0.5 percentage point"が単数となる理由等について 2 2023/05/11 10:41
- C言語・C++・C# C# で、あるフォルダー内にあるすべてのテキストファイルを別のフォルダーにコピーする。 4 2022/11/21 13:23
- Java javaでのプログラム(配列)について質問です. 2 2022/10/14 22:27
- Excel(エクセル) エクセルシート中の全角英数字を半角に変換したい 4 2022/07/07 13:14
- Visual Basic(VBA) 複数のcsvファイルをExcelに一括変換したい 2 2023/03/03 12:44
- Visual Basic(VBA) 複数シートの複数列に入力されているデータを重複なしで抽出するVBAを作りたいです。 9 2022/06/17 10:33
- Visual Basic(VBA) ExcelVBAに関する質問 3 2023/02/17 10:47
- Visual Basic(VBA) 前回ご教授いただいたコードに覚えたてのループ処理で品名りんごAから順に20回for nextでループ 7 2023/01/13 22:01
- Visual Basic(VBA) ①ExcelVBAでカレンダーを作り、別のユザーフォームで日付を入力したいのですがエラーになります。 1 2023/02/17 18:39
このQ&Aを見た人はこんなQ&Aも見ています
-
プロが教えるわが家の防犯対策術!
ホームセキュリティのプロが、家庭の防犯対策を真剣に考える 2組のご夫婦へ実際の防犯対策術をご紹介!どうすれば家と家族を守れるのかを教えます!
-
C# ソケット通信でデータ受信時の欠損について
C言語・C++・C#
-
UDP通信におけるbind関数について
C言語・C++・C#
-
バッファ領域がありません。とエラーを起こします
Visual Basic(VBA)
-
-
4
UDP受信時の通信異常検知について
C言語・C++・C#
-
5
UDPで受信終了の合図を出して受信終了させる
Java
-
6
UDP通信する時に、相手にどうやって自分のポート番号を教える?
Java
-
7
UdpClient 送信元のIPアドレスの指定方法
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
rs232cでの受信データ(mscomm)...
-
socket: recvはいつ,どれだけ...
-
WaitForMultipleObjects関数の...
-
バイナリデータ受信時のデータ順
-
Connection reset by peer
-
winsock recvでデータの取得方法
-
COMポートの同時オープン同時読...
-
visual c# 2010 シリアル通信ア...
-
C# シリアル通信でデータ受信...
-
「スイッチングハブのバッファ...
-
バッファ領域がありません。と...
-
Perlでイベント処理?
-
緯度、経度の 10進法と 60進法...
-
Macターミナルで実行中のプログ...
-
VBAの配列サイズとメモリに関して
-
スレッドの安全な終了のさせ方
-
バックグラウンドのプロセスの...
-
Excelでのセル内容の高速消去方法
-
explorer.exeが異様にメモリを食う
-
C言語で、メモリを解放しないで...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C# シリアル通信でデータ受信...
-
WriteFile()でのデータ送信がで...
-
winsockでソケット通信の開発を...
-
「スイッチングハブのバッファ...
-
socket: recvはいつ,どれだけ...
-
シリアル通信の出力バッファと...
-
Connection reset by peer
-
RS232C通信(PC⇔PLC)
-
RS-232Cでバイナリデータを受信...
-
WaitForMultipleObjects関数の...
-
Linuxでのシリアル通信について...
-
rs232cでの受信データ(mscomm)...
-
UDP処理のエラーについて
-
SocketのSend関数でのCLOSEの検...
-
ソケット通信内 read関数について
-
recv関数の受信結果について
-
シリアルポート通信
-
MSCommでoutputできない
-
SerialPortのDataReceivedイベ...
-
COMポートの同時オープン同時読...
おすすめ情報