【发布时间】:2016-11-27 15:11:12
【问题描述】:
我正在编写一个需要使用 UDP 的单声道 C# 应用程序。我正在编写我的测试套件,以便确保使用 NUnit 正确接收数据包。
我用UdpCom 类制作了一个最小的工作示例,该类应该现在就监听并打印出它在回调方法中接收到的字节。
我最小的UdpCom 类看起来像:
using System;
using System.Net;
using System.Net.Sockets;
namespace UdpPractice
{
public class UdpState
{
public UdpClient client;
public IPEndPoint endpoint;
public UdpState(UdpClient c, IPEndPoint iep)
{
this.client = c;
this.endpoint = iep;
}
}
public class UdpCom
{
public UdpState uState;
public UdpClient uClient;
public IPAddress address;
public int port;
public IPEndPoint uEndpoint;
public UdpCom (IPAddress address, int port)
{
uEndpoint = new IPEndPoint (address, port);
uClient = new UdpClient (uEndpoint);
uState = new UdpState (uClient, uEndpoint);
uClient.BeginReceive (new AsyncCallback(RxCallback), uState);
}
public void RxCallback(IAsyncResult result)
{
UdpState rState = (UdpState)(result.AsyncState);
UdpClient rClient = rState.client;
IPEndPoint rEndPoint = rState.endpoint;
byte[] rxBytes = rClient.EndReceive (result, ref rEndPoint);
Console.WriteLine ("Received Bytes ___________________________");
Console.WriteLine (rxBytes.ToString ());
rClient.BeginReceive (new AsyncCallback(RxCallback), rState);
}
}
}
我的简单测试实例化了这个类,然后向它发送一个虚拟字节包。我现在不测试结果,只是在我的RxCallback 方法中放置一个断点。
这是我的 NUNIT 测试:
using NUnit.Framework;
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using UdpPractice;
namespace UdpTest
{
[TestFixture ()]
public class Test
{
[Test ()]
public void TestCase ()
{
// Setup Receiver
IPAddress address = new IPAddress (new byte[] { 127, 0, 0, 1 });
int port = 14580;
UdpCom com = new UdpCom (address, port);
com.uClient.Connect (com.uEndpoint);
// Set up sender
UdpClient sender = new UdpClient(new IPEndPoint (address, port));
sender.Connect (address, port);
// Dummy Data
byte [] dummyData = new byte[] {1, 2, 3, 4, 4, 5};
sender.Send (dummyData, dummyData.Length);
Thread.Sleep (100);
// Close
sender.Close ();
com.uClient.Close ();
}
}
}
我的问题是,当我在尝试检索字节的行中的 RxCallback 方法时,我得到了这个异常:
System.ObjectDisposedException has been thrown
Cannot access a disposed object.
Object name: System.Net.Sockets.UdpClient
我希望能够将这些字节存储在我的 UdpCom 类中的队列中,但我一开始就无法访问它们。
我在这里可能无法理解一些基本的 UDP 概念,但它看起来很简单。
我一直关注的 udp 示例是:
- https://yal.cc/cs-dotnet-asynchronous-udp-example/
- https://www.codeproject.com/articles/132623/basic-udp-receiver
编辑
我更新了我的课程和测试如下,所以我不使用本地环回。但我仍然得到同样的例外。
UdpCom 现在是:
using System;
using System.Net;
using System.Net.Sockets;
namespace UdpPractice
{
public class UdpState
{
public UdpClient client;
public IPEndPoint endpoint;
public UdpState(UdpClient c, IPEndPoint iep)
{
this.client = c;
this.endpoint = iep;
}
}
public class UdpCom
{
public UdpState uState;
public UdpClient uClient;
public IPAddress address;
public int port;
public IPEndPoint uEndpoint;
public UdpCom (IPAddress address, int port)
{
uEndpoint = new IPEndPoint (address, port);
uClient = new UdpClient (uEndpoint);
uState = new UdpState (uClient, uEndpoint);
uClient.BeginReceive (new AsyncCallback(RxCallback), uState);
}
public void RxCallback(IAsyncResult result)
{
UdpState rState = (UdpState)(result.AsyncState);
UdpClient rClient = rState.client;
IPEndPoint rEndPoint = rState.endpoint;
byte[] rxBytes = rClient.EndReceive (result, ref rEndPoint);
Console.WriteLine ("Received Bytes ___________________________");
Console.WriteLine (rxBytes.ToString ());
rClient.BeginReceive (new AsyncCallback(RxCallback), rState);
}
}
}
测试是:
using NUnit.Framework;
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using UdpPractice;
namespace UdpTest
{
[TestFixture ()]
public class Test
{
[Test ()]
public void TestCase ()
{
// Setup Receiver
IPAddress address = new IPAddress (new byte[] { 192, 168, 1, 161 });
int port = 14580;
UdpCom com = new UdpCom (IPAddress.Any, port);
// com.uClient.Connect (com.uEndpoint);
// Set up sender
UdpClient sender = new UdpClient(new IPEndPoint (address, port));
sender.Connect (address, port);
// Dummy Data
byte [] dummyData = new byte[] {1, 2, 3, 4, 4, 5};
sender.Send (dummyData, dummyData.Length);
Thread.Sleep (100);
// Close
sender.Close ();
com.uClient.Close ();
}
}
}
【问题讨论】:
-
您可以使用的另一个资源:stackoverflow.com/a/19787486/5233410
-
您只能有一个具有相同 3 个属性的连接:源 IP、目标 IP、端口号。在本地连接时,您必须确保客户端和服务器没有使用相同的 3 个属性,解决方案是让服务器在 IPAny 上侦听,客户端连接到 PC 的 IP 地址。您正在使用 PC 127.0.0.1 的 LoopBack 地址,通常是 LocalHost。 Net库不允许客户端使用环回IP,会报异常。
-
所以我拿出我的
com.uClient.Connect (com.uEndpoint);线,让com客户端使用UdpCom com = new UdpCom (IPAddress.Any, port);在IPAny 上侦听,发件人UdpClient 连接到192.168.1.161。我得到了同样的例外。我更新了我的问题以反映这些变化。 -
这种行为是正常的。中断异步套接字操作的唯一方法是关闭套接字。当你这样做时,任何挂起的回调都将被调用,但套接字已经被释放。解决方案是在
.EndReceive周围做一个catch (ObjectDisposedException)。是的,我知道通常你不应该捕捉ObjectDisposedException,但否则你必须添加一个线程安全标志来检测处置,这更复杂,收获甚微。另见here。
标签: c# unit-testing udp