Sya*_*hya 8 c# udpclient beginreceive
我想做这个
for (int i = 0; i < 100; i++ )
{
Byte[] receiveBytes = receivingUdpClient.Receive(ref RemoteIpEndPoint);
}
Run Code Online (Sandbox Code Playgroud)
但UdpClient.Receive
我不得不使用,而不是使用UdpClient.BeginReceive
.问题是,我该怎么做?没有很多样本使用BeginReceive
,MSDN示例根本没有帮助.我应该使用BeginReceive
,还是只在一个单独的线程下创建它?
我一直都是ObjectDisposedException
例外.我只收到第一个发送的数据.下一个数据将抛出异常.
public class UdpReceiver
{
private UdpClient _client;
public System.Net.Sockets.UdpClient Client
{
get { return _client; }
set { _client = value; }
}
private IPEndPoint _endPoint;
public System.Net.IPEndPoint EndPoint
{
get { return _endPoint; }
set { _endPoint = value; }
}
private int _packetCount;
public int PacketCount
{
get { return _packetCount; }
set { _packetCount = value; }
}
private string _buffers;
public string Buffers
{
get { return _buffers; }
set { _buffers = value; }
}
private Int32 _counter;
public System.Int32 Counter
{
get { return _counter; }
set { _counter = value; }
}
private Int32 _maxTransmission;
public System.Int32 MaxTransmission
{
get { return _maxTransmission; }
set { _maxTransmission = value; }
}
public UdpReceiver(UdpClient udpClient, IPEndPoint ipEndPoint, string buffers, Int32 counter, Int32 maxTransmission)
{
_client = udpClient;
_endPoint = ipEndPoint;
_buffers = buffers;
_counter = counter;
_maxTransmission = maxTransmission;
}
public void StartReceive()
{
_packetCount = 0;
_client.BeginReceive(new AsyncCallback(Callback), null);
}
private void Callback(IAsyncResult result)
{
try
{
byte[] buffer = _client.EndReceive(result, ref _endPoint);
// Process buffer
MainWindow.Log(Encoding.ASCII.GetString(buffer));
_packetCount += 1;
if (_packetCount < _maxTransmission)
{
_client.BeginReceive(new AsyncCallback(Callback), null);
}
}
catch (ObjectDisposedException ex)
{
MainWindow.Log(ex.ToString());
}
catch (SocketException ex)
{
MainWindow.Log(ex.ToString());
}
catch (System.Exception ex)
{
MainWindow.Log(ex.ToString());
}
}
}
Run Code Online (Sandbox Code Playgroud)
是什么赋予了?
顺便说一下,一般的想法是:
小智 7
它似乎UdpClient.BeginReceive()
并UdpClient.EndReceive()
没有得到很好的实施/理解.当然,与TcpListener的实现方式相比,使用起来要困难得多.
您可以采取一些措施来UdpClient.Receive()
更好地利用这项工作.首先,在底层套接字客户端上设置超时将使控制能够通过(到异常),允许控制流继续或循环播放.其次,在一个新的线程(其中我还没有创建)创建UDP监听,你可避免的半阻挡作用UdpClient.Receive()
的功能,如果你这样做是正确,你可以有效地中止该线程以后.
以下代码分为三部分.第一个和最后一个部分应分别位于入口和出口点的主循环中.第二部分应该在您创建的新线程中.
一个简单的例子:
// Define this globally, on your main thread
UdpClient listener = null;
// ...
// ...
// Create a new thread and run this code:
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 9999);
byte[] data = new byte[0];
string message = "";
listener.Client.SendTimeout = 5000;
listener.Client.ReceiveTimeout = 5000;
listener = new UdpClient(endPoint);
while(true)
{
try
{
data = listener.Receive(ref endPoint);
message = Encoding.ASCII.GetString(data);
}
catch(System.Net.Socket.SocketException ex)
{
if (ex.ErrorCode != 10060)
{
// Handle the error. 10060 is a timeout error, which is expected.
}
}
// Do something else here.
// ...
//
// If your process is eating CPU, you may want to sleep briefly
// System.Threading.Thread.Sleep(10);
}
// ...
// ...
// Back on your main thread, when it's exiting, run this code
// in order to completely kill off the UDP thread you created above:
listener.Close();
thread.Close();
thread.Abort();
thread.Join(5000);
thread = null;
Run Code Online (Sandbox Code Playgroud)
除此之外,您还可以检查UdpClient.Available > 0
以确定在执行之前是否有任何UDP请求排队UdpClient.Receive()
- 这完全消除了阻塞方面.我建议您谨慎尝试,因为此行为不会出现在Microsoft文档中,但似乎确实有效.
注意:
您在研究此问题时可能找到的MSDN exmaple代码需要一个额外的用户定义类 - UdpState.这不是.NET库类.在研究这个问题时,这似乎让很多人感到困惑.
该超时不必严格进行设置,以使您的应用程序完全退出,但他们会允许你做其他事情在这个循环,而不是永远阻塞.
该listener.Close()命令是非常重要的,因为它迫使UdpClient抛出一个异常,并退出循环,使Thread.Abort的()得到处理.如果没有这个,您可能无法正常终止侦听器线程,直到它超时或收到UDP数据包导致代码继续通过UdpClient.Receive()块.
只是为了补充这个无价的答案,这是一个经过实践检验的代码片段.(这里是Unity3D上下文,但当然对于任何c#.)
// minmal flawless UDP listener per PretorianNZ
using System.Collections;
using System;
using System.Net.Sockets;
using System.Net;
using System.Threading;
void Start()
{
listenThread = new Thread (new ThreadStart (SimplestReceiver));
listenThread.Start();
}
private Thread listenThread;
private UdpClient listenClient;
private void SimplestReceiver()
{
Debug.Log(",,,,,,,,,,,, Overall listener thread started.");
IPEndPoint listenEndPoint = new IPEndPoint(IPAddress.Any, 1260);
listenClient = new UdpClient(listenEndPoint);
Debug.Log(",,,,,,,,,,,, listen client started.");
while(true)
{
Debug.Log(",,,,, listen client listening");
try
{
Byte[] data = listenClient.Receive(ref listenEndPoint);
string message = Encoding.ASCII.GetString(data);
Debug.Log("Listener heard: " +message);
}
catch( SocketException ex)
{
if (ex.ErrorCode != 10060)
Debug.Log("a more serious error " +ex.ErrorCode);
else
Debug.Log("expected timeout error");
}
Thread.Sleep(10); // tune for your situation, can usually be omitted
}
}
void OnDestroy() { CleanUp(); }
void OnDisable() { CleanUp(); }
// be certain to catch ALL possibilities of exit in your environment,
// or else the thread will typically live on beyond the app quitting.
void CleanUp()
{
Debug.Log ("Cleanup for listener...");
// note, consider carefully that it may not be running
listenClient.Close();
Debug.Log(",,,,, listen client correctly stopped");
listenThread.Abort();
listenThread.Join(5000);
listenThread = null;
Debug.Log(",,,,, listener thread correctly stopped");
}
Run Code Online (Sandbox Code Playgroud)
我认为您不应该在循环中使用它,而是每当调用 BeginReceive 回调时,您都会再次调用 BeginReceive ,并且如果您想将数量限制为 100,则保留一个公共变量用于计数。
归档时间: |
|
查看次数: |
20364 次 |
最近记录: |