• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:UDP処理のエラーについて)

UDP処理のエラーについて

このQ&Aのポイント
  • UDP処理中にエラーが発生する原因として、ポートのバッファが限界に達したことが考えられます。
  • このエラーは、システムのバッファ領域が不足しているか、キューがいっぱいであることが原因となっています。
  • エラーを解決するには、バッファサイズを拡張するか、キューサイズを調整する必要があります。

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

  • ベストアンサー
回答No.4

> 一度Sendした場合、受信待ち状態が解除されるので、 > 再度BeginReceiveを呼び出しています。 元々コールバック関数中でBeginReceiveを呼び出しておらず, その場合には一度だけコールバック関数が呼ばれるために, Sendで受信待ち状態が解除されると勘違いした,ということはないですか。 UdpClient.Sendはsendto WinSock2 APIを呼び出すのですが, このAPIはRecvFrom WinSock2 APIによるoverlapped I/Oを阻害しません。 わかりにくいなら,受信用のソケットと送信用のソケットを分離してしまうのも一つの方法だと思います。

kenji0508
質問者

お礼

大変申し訳ありません。 ご指摘の通り、BeginReceiveの認識に誤りがありました。 コールバック関数中でBeginReceiveは呼び出していたのですが、 送信処理でもBeginReceiveを呼び出していました。 Sendを実行すると受信待ちが解除されるのだと思っていました。 送信処理にあるBeginReceiveを削除したところ、正常に動作するようになりました。 いつも1時間で落ちていたのに4時間経っても問題ありません。 ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (3)

回答No.3

> lUdpClient.udp.BeginReceive(New System.AsyncCallback(AddressOf receivecallback), lUdpClient) #ここでエラー ここは送信処理を行うのではないのですか? どう見ても受信処理をさせようとしていますが。 実際に送信するつもりでBeginReceiveしていれば, タイマーでBeginReceiveの呼び出しが蓄積していきますから例外が発生します。

kenji0508
質問者

お礼

ご回答ありがとうございます。 申し訳ありません。ソースが足りませんでした。 以下のように送信処理を行っています。 ' リモートホストを指定してデータを送信 lUdpClient.udp.Send(sendBytes, sendBytes.Length, remoteHost, remotePort) lUdpClient.udp.BeginReceive(New System.AsyncCallback(AddressOf receivecallback), lUdpClient) #ここでエラー 一度Sendした場合、受信待ち状態が解除されるので、 再度BeginReceiveを呼び出しています。 やはり送信処理中にBeginReceiveを使用しているのが原因なのでしょうか。 しかし、受信待ち状態にするにはこの方法しかないと思い、 仕方なくBeginReceiveを使用しています。

全文を見る
すると、全ての回答が全文表示されます。
回答No.2

大量にUdpClientでBeginReceiveさせ例外を起こさせたところ,どうもOS側のキューが不足しているようです。 # 手元の環境のソースだと,Socket.csの4967行目。 なので,ThreadPoolは関係ありませんでした。 WSARecvFrom APIのエラーにもWSAENOBUFSはないので,通常は起こらないと見られているのでしょう。 確実な解決策は,overlapped I/Oの数を減らすことしかないと思います。 まず,BeginReceiveをそれだけたくさん行う必要があるのでしょうか。 例えば,最大で3個程度作るだけにしてしまえば,この例外が起きることはなくなると思います。 # 20件/secであればこれでさばけると思いますが。

kenji0508
質問者

お礼

ご回答ありがとうございます。 送信処理は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.1

えーっと,OSが認識するプロセッサの個数 (タスクマネージャのパフォーマンスタブのCPUの個数) はいくつですか。 これが3以下であれば,3001個もスレッドを非同期I/Oを同時に実行することはできません。 # 4以上でも,3001個も非同期I/Oを作るのが良いとは言えませんが。 可能であるならば,そもそもBeginReceiveの回数を減らし,コールバック関数で再度BeginReceiveするなどしてみてはどうでしょうか。

参考URL:
http://msdn.microsoft.com/ja-jp/library/system.threading.threadpool.aspx
kenji0508
質問者

お礼

ご回答ありがとうございます。 デュアルコアですので2つになります。 >可能であるならば,そもそもBeginReceiveの回数を減らし,コールバック関数で再度BeginReceiveするなどしてみてはどうでしょうか。 コールバック関数で再度BeginReceiveを実行したところ1時間ほどで同じ下記エラーが発生しました。 1秒間に20回くらいUDPでデータを受信しているため、パケットの量が多すぎてエラーになったのでしょうか。 システムのバッファ領域が不足しているか、またはキューがいっぱいなため、ソケット操作を実行できませんでした。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • javaのUDP受信プログラムについて

    UDPで数値データを受信してある処理をしようと考えております。 そこで↓のページで公開されている受信プログラムを使用してデータを受信しました。 http://news.mynavi.jp/column/java/052/index.html import java.net.*; public class UDPServer { public static void main(String[] argv) throws Exception { // 5100番ポートを監視するUDPソケットを生成 DatagramSocket receiveSocket = new DatagramSocket(5100); // 受け付けるデータバッファとUDPパケットを作成 byte receiveBuffer[] = new byte[1024]; DatagramPacket receivePacket = new DatagramPacket(receiveBuffer, receiveBuffer.length); while (true) { // UDPパケットを受信 receiveSocket.receive(receivePacket); // 受信したデータを標準出力へ出力 System.out.println (new String(receivePacket.getData(), 0, receivePacket.getLength())); } } } 別のプログラムから「50」という数値を送信し、上記のプログラムで受信すると、勝手にASCIIコードに変換されてしまっているようで、ASCIIコードの10進数の50にあたる「2」が出力されてしまいます。 これをASCIIコードに変換せずに、表示させる方法を教えて下さい。 もしくは、受信データをバイナリで表示する方法があれば、そちらも教えていただけるとありがたいです。 よろしくお願いします。

    • ベストアンサー
    • Java
  • Linux UDPサーバーに対するクライアント数

    CentOS release 4.6(カーネル 2.6.9-67)上でUDPサーバーを開発していますが、同一ポートに対して複数クライアントからの通信を確認しています。250クライアント位までは同時通信してもパケットロスはほとんど発生しないのですが、250クライアント以上で同時通信を行うと、最大250クライアント位まで通信可能ですが、残りのクライアントについてクライアントからのパケットロスが発生します。 UDPなので多少のパケットロスしかたないのですが、なぜ最大250クライアント位までしか同時通信ができないかを調べています。 UDPサーバー側の送受信バッファはソケットオプションで大きめに設定しています。 カーネルパラメータやソケットオプションなどで、同一ポートに対しての同時通信が可能なクライアントを制限するようなパラメータはあるのでしょうか? 有識者の方がいましたらご教示下さい。 宜しくお願いいたします。

  • UDP/IPでのソケット作成について(winsock)

    UDP/IPでのソケット作成について(winsock) 開発環境VC++.NET、O/S WIN2000にてソケットプログラミング(winsock2.0)をしています。 コンソールプログラミングではありませんが、WindProcは持っていません。 UDPサーバーを作り、複数クライアントの対応をしたいと考えています。 クライアントAからの通信やりとり中に クライアントBからの通信がきたら、そちらとも通信やりとりを(自動で)行いたい。 ここで問題なのが、クライアントAの要求ポートが15000で、 クライアントBの要求ポートも15000なのです。 同じ既に開いているポートでソケット作成しようとしても、socket()関数はエラーを返してくるのですが、 やり方を工夫すれば、同一ポートでの複数クライアント対応は可能なのでしょうか。不可能なのでしょうか。 可能であれば、やり方、ヒント等教えてください。よろしくお願いします。 追記 (1)TCP/IPでは、同一ポートでソケット作成が可能でした。ネットで探したサンプルプログラムが  そのような動きをしていたのですが、UDPに書換えることはできませんでした。  http://eternalwindows.jp/network/winsock/winsock04s.html (2)UNIXの場合fork()処理後に socket()作成 → bind()で同一ポートでの複数クライアント対応が  上手くいくらしいのですが、Windowsではマルチスレッド等をうまく活用すれば、  fork()と同様の処理が可能になり、目的が達成できるでしょうか。

  • クライアント上のC++でサーバーとソケット送信

    クライアント(Windows7)上でC++を使って、サーバー側(Windows)に対してデータを送りたいです (ソケット通信?)。 サーバ受信側はC#を使ったプログラムで以下のような感じで考えてます。 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; using System.IO; namespace ConsoleApplication1 {   class Program   {     static void Main(string[] args)     {       int port = 2222;       System.Net.IPAddress ip = IPAddress.Parse("127.0.0.1");       System.Net.Sockets.TcpListener server = new TcpListener(ip, port);       Console.WriteLine("Enter押してください");       ConsoleKeyInfo info = Console.ReadKey();       if (info.Key == ConsoleKey.Enter)       {         Console.WriteLine("サーバー待機中");         server.Start();         TcpClient client = server.AcceptTcpClient();         NetworkStream ns = client.GetStream();         StreamWriter sw = new StreamWriter(ns);         Console.WriteLine(sw);       }     }   } } C++のことがよくわかってないので、送信側でC++を使ってどのように 送信すればいいのかわかりません。 送信するデータはINT型で、1秒間に1回、繰り返し送ります。 よろしくお願いします。

  • new領域確保について

    お世話になります new演算子の使用方法について教えてください。 new演算子は、動的確保を行なう際に使用する事は知っております。 もう1つの使用理由として、関数内のローカル変数領域が多大になる場合に 使用すると聞いた事があります これは、スタック領域を圧迫しないためと説明を受けた記憶があります これがあってるとしたら、どれくらいの変数容量を宣言する際に、new演算子を使用するのでしょうか? よろしくお願い致します

  • UdpClient 送信元のIPアドレスの指定方法

    System.Net.Sockets.UdpClient クラスを使用してのソケット通信を行っています。 プログラムでは、送信元のポート番号のみ引数に渡すだけで それまで順調に通信は行っていたのですが //localPort=送信元ポート番号 fUdp = new System.Net.Sockets.UdpClient(localPort); 新たに ネットワークインターフェースカードを追加して、IPアドレスを後から 挿した方に変更してから、通信がうまく動作しなくなってしまいました。 おそらくは、IPアドレスが複数ある為に、うまく動かないのかな?と思い 送信元のポート番号だけでなく、送信元のIPアドレスも合わせて指定してやれば 直ると思い調べていたのですが、送信元IPアドレスの指定する方法が判りません AddressFamily で指定するのかなとも思ったのですが、ヘルプを見てもよくわからずに 行き詰ってしまいました。 もしよろしければ、送信元のIPアドレスを指定する方法をご教授ねがえませんでしょうか

  • winsockのポート指定について

    winsockを使ったUDPのプログラムを作成しています。開発環境はVC.NET/win2000です。 UDPサーバで受信側のプログラムとして、   ・sin_port に受信ポート番号を設定   ・socket   ・bind という流れでソケット生成をしています。 上記の流れを1プロセスで1度行って、1プロセスにつき1ポートに対応した メッセージを受信しているのですが、 1プロセスで複数ポートを対象に受信を行うことは可能なのでしょうか?   ・ポート番号を複数指定する   ・ソケットを複数生成する など・・・  方法がわかりません。 すみませんが回答をよろしくおねがいします。

  • WinSockを用いたUDP送受信ソケットプログラミングについて

    こんにちは。 現在、VC++.NETでWinSockを用いたUDPソケットプログラミングを行っています。以下のようなプログラムを作りたいと思っているのですがうまく動作しません。 [概要] A:送信端末 B:受信端末 1.Aから文字列"send"をB端末へ送信。 2."send"を受信した受信端末Bは、A端末へ文字列"ok"を送信。 この1と2の動作を行わせたいと思っています。この場合、A,B端末は送信と受信を行う必要があります。 [問題点(うまくいかない点)] A→Bへ"send"は送信でき、B端末で受信できるのですが、B端末からA端末へ送信できません。B端末で送信できているのか、それともA端末で受信できていないのか?が分からない状態です。 [気づいた点] ポート番号を分ける必要があるのでしょうか?例えば、A→Bへは9000番。B→Aへは9001番という意味です。 送信と受信を行うため、送信・受信で2つのUDPソケットを使用する必要があるのでしょうか?例えば、 s1 = socket(AF_INET, SOCK_DGRAM, 0);←送信に利用 s2 = socket(AF_INET, SOCK_DGRAM, 0);←受信に利用 よろしくお願いします。

  • vb2005でUDP受信時にフォームが表示されない

    はじめまして VB2005でUDPのメッセージを受信してForm上のLabelに受信内容を表示させるサンプルプログラムを作成したのですが、「デバック開始」をクリックしてもFormのウィンドウ自体が表示されません。 イミディエイトにdebug.printで受信データは表示されていますのでプログラム自体は正常に動作しているようです。 どなたかアドバイスをいただけませんでしょうか。 Public Class Form1 Dim localport As Integer = 1111 Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load '文字コードを指定する Dim enc As System.Text.Encoding = System.Text.Encoding.UTF8 ' バインド Dim udp As New System.Net.Sockets.UdpClient(localport) ' 受信 Dim remoteEP As System.Net.IPEndPoint = Nothing Debug.Print("受信開始") Do My.Application.DoEvents() Dim rcvBytes As Byte() = udp.Receive(remoteEP) Dim rcvMsg As String = enc.GetString(rcvBytes) My.Application.DoEvents() Debug.Print("受信メッセージ:" & rcvMsg) Label1.Text = rcvMsg Loop End Sub End Class

  • UDP通信について

    前回のことでかなり言われたので改変版を見てもらいたいと思います。 TCPと伝えていましたが今回、UDPに変えました。 ヘッダーはこのようになっております。 ==wsock.h== #include <Windows.h> #include <stdio.h> #pragma comment(lib,"WSock32.lib") #define PORT_NO 8000 ポート番号 #define SERVER_NAME "" enum MINE{ NONE, SERVER, CLIENT }; ソケット通信 class WSOCK{ private: WSADATA wsaData; SOCKET s; SOCKADDR_IN saddr; int rtn; int state; MINE mineFlg; char szStr[256]; エラーメッセージ用 u_short port; 変換後のポート番号 int fromlen; 受信したサイズ HOSTENT *lpHost; ホスト情報 ファイルディスクプリタをまとめた構造体 //→ソケット判別する為の管理情報 fd_set fds,readfds; public: char szRcvBuf[1024]; 受信バッファ char szSndBuf[1024]; 送信バッファ SOCKADDR_IN from; ソケットアドレス構造体 WSOCK(); ~WSOCK(); bool ServerRcv(); 受信 bool ServerSnd();送信 bool CliantRcv();受信 bool CliantSnd();送信 void SarverSet(); void ClientSet(); bool EnumMyIPAddress(); }; ==wsock.cpp== #include "wsock.h" コンストラクタ WSOCK::WSOCK(){ //WinSock初期化 rtn = WSAStartup(MAKEWORD(2,2),&wsaData); if(rtn != 0){ MessageBox(NULL,"WSAStartup失敗", "ERROR",MB_OK); state = -1; } ソケットを開く s = socket(AF_INET,SOCK_DGRAM,0); if(s<0){ MessageBox(NULL,"ソケットをオープンできません", "eRROR",MB_OK); WSACleanup(); state = 2; } 0で初期化 memset(&saddr,0,sizeof(SOCKADDR_IN)); saddr.sin_family = AF_INET;//アドレスファミリー saddr.sin_port = htons(PORT_NO);//ポート mineFlg = SERVER; サーバ側設定 if(mineFlg == SERVER) { SarverSet(); } if(mineFlg == CLIENT) {クライアント ClientSet(); } } WSOCK::~WSOCK(){ closesocket(s); ソケットのリソース解放 rtn = WSACleanup(); if(rtn == SOCKET_ERROR){ MessageBox(NULL,"WSACleanup失敗","ERrOR",MB_OK); state = -2; } } //受信 bool WSOCK::ServerRcv(){ 読み込み用fd_setの初期化 selectが毎回内容を上書きしてしまうので毎回初期化 memcpy(&fds,&readfds,sizeof(fd_set)); struct timeval timeout = {0,0};   //{1秒以上の部分()s、1秒以下の部分(ms)} fdsに設定されたソケットが読み込み可能になるまで待つ select(0,&fds,NULL,NULL,&timeout); ソケット読み込み可能データがある場合 if(FD_ISSET(s,&fds)){ fromlen = (int)sizeof(from); //nullで初期化 memset(szRcvBuf,'\0',sizeof(szRcvBuf)); //受信処理 rtn = recvfrom(s,szRcvBuf,(int)sizeof(szRcvBuf)-1,0, (SOCKADDR*)&from,&fromlen); if(rtn == SOCKET_ERROR){ MessageBox(NULL,"recvfromエラー","ERRoR",MB_OK); return false; } } szRcvBuf[rtn] | '\0';//NULLコード if(strcmp(szRcvBuf,"c_end") == 0){ MessageBox(NULL,"クライアントが接続を切りました","ERROr",MB_OK); return false; } return true; } 送信 bool WSOCK::ServerSnd(){ char buf[1024]; memset(buf,0,sizeof(buf)); //_snprintf:書式指定文字付きデータ書き込み _snprintf(buf,sizeof(buf),"data to port 8000"); //送信処理 rtn = sendto(s,szSndBuf,(int)strlen(szSndBuf)+1, 0,(LPSOCKADDR)&from, 送り先サーバ/クライアント sizeof(from)); サイズ if(rtn != (int)strlen(szSndBuf)+1){ MessageBox(NULL,"sendtoエラー","サーバーエラ",MB_OK); closesocket(s); WSACleanup(); return false; } return true; } 受信 bool WSOCK::CliantRcv(){ fromlen = (int)sizeof(from); //nullで初期化 memset(szRcvBuf,'\0',sizeof(szRcvBuf)); //受信処理 rtn = recvfrom(s,szRcvBuf,(int)sizeof(szRcvBuf)-1,0, (SOCKADDR*)&from,&fromlen); if(rtn == SOCKET_ERROR){ MessageBox(NULL,"recvfromエラー","ERRoR",MB_OK); return false; } szRcvBuf[rtn] | '\0'; //NULLコード if(strcmp(szRcvBuf,"s_end") == 0){ MessageBox(NULL,"接続を切りました","ERROr",MB_OK); return false; } return true; } 送信 bool WSOCK::CliantSnd(){ 送信処理 rtn = sendto(s,szSndBuf,(int)strlen(szSndBuf)+1, 0,(LPSOCKADDR)&saddr, 送り先サーバ/クライアント sizeof(saddr)); サイズ if(rtn != (int)strlen(szSndBuf)+1){ MessageBox(NULL,"sendtoエラー","erROR",MB_OK); closesocket(s); WSACleanup(); return false; } return true; } void WSOCK::SarverSet(){ saddr.sin_addr.s_addr = htonl(INADDR_ANY); ソケットにローカルアドレスを関連付ける if(bind(s,(LPSOCKADDR)&saddr, (int)sizeof(saddr)) == SOCKET_ERROR){ MessageBox(NULL,"bindエラー","er",MB_OK); closesocket(s); WSACleanup(); state = -3; } FD_ZERO(&readfds); FD_SET(s,&readfds); } void WSOCK::ClientSet(){    クライアント側設定    ホスト名からホスト情報を取得 lpHost = gethostbyname(SERVER_NAME); サーバのアドレスをセット memcpy(&(saddr.sin_addr), lpHost->h_addr_list[0], //サーバのアドレス lpHost->h_length); } となっております。