我需要从我的ERP系统(Dynamics Nav)中接收小的UDP数据包。我用互联网上的一些代码创建了一个类(我第一次使用UDP代码),添加了一个COM接口并在Nav中使用生成的DLL。它立即工作,但我意识到udp.Close()函数并没有真正关闭它,我不能再次实例化该类。
在stackoverflow和其他网站上查看有关udp.BeginReceive()的许多主题后,我理解了这一点。在关闭upd对象之前需要进行最后的udp.EndReceive调用。
由于类在后台运行,因此使用udp.BeginReceive定义的回调函数。然后,回调函数通过调用udp.EndReceive获取数据,最后将其存储到字符串中。只要希望数据通过简单属性,Nav就可以检索该字符串。
public string GetMessage { get { return(message); } }
public void Start()
{
udp = new UdpClient(PORT_NUMBER);
StartListening();
}
public void Stop()
{
udp.Close();
}
private void StartListening()
{
ar_ = udp.BeginReceive(Receive, new object());
}
private void Receive(IAsyncResult ar)
{
IPEndPoint ip = new IPEndPoint(IPAddress.Any, PORT_NUMBER);
byte[] bytes = udp.EndReceive(ar, ref ip);
message = Encoding.ASCII.GetString(bytes);
StartListening();
}
除了......外,其他情况都很好。
Nav调用Start(),它发出StartListening(),它定义了回调函数。通过udp.EndReceive接收数据后,它再次调用StartListening() - 这部分工作正常。
然而,当Nav调用Stop()函数时,麻烦就开始了,我明白这是因为没有最终调用EndReceive,因此没有打开会话。
有人可能会说,为什么在udp.Close()之前不要在Stop()函数中执行EndReceive()?好吧,因为我找不到那个电话的正确参数。
其实我确实有一个工人阶级。我不会尝试在Stop()函数中关闭会话,而是设置bool变量。下次发出回调函数时,取决于bool,它不会执行StartListening()而是执行upd.CLose()。最后,为了确保有数据来发出回调函数,我调用我的Send()函数发送一些单个字符。
虽然下面的代码工作正常,但我知道这有点疯狂:
public string GetMessage { get { return(message); } }
public void Start()
{
active = true;
udp = new UdpClient(PORT_NUMBER);
StartListening();
}
public void Stop()
{
active = false; // force callback function to close session
Send("x"); // issue callback function ... crazy
//udp.Close();
}
private void StartListening()
{
ar_ = udp.BeginReceive(Receive, new object());
}
private void Receive(IAsyncResult ar)
{
IPEndPoint ip = new IPEndPoint(IPAddress.Any, PORT_NUMBER);
byte[] bytes = udp.EndReceive(ar, ref ip);
message = Encoding.ASCII.GetString(bytes);
if (active) StartListening(); else udp.Close();
}
在调用udp.Close()之前,是否有人提示如何在我的Stop()函数中发出EndReceive()?
提前致谢
迈克尔
答案 0 :(得分:1)
我最近发现一个解决方案只是使用Thread()而不是async接收 - 到目前为止工作完美:
public class Bos_UDP
{
private UdpClient udp;
const int PORT_NUMBER = 15000;
private String message = "";
public Thread receiveThread;
public string GetMessage { get { return(message); } }
public void Start()
{
udp = new UdpClient(PORT_NUMBER);
receiveThread = new Thread(ThreadReceive);
receiveThread.Start();
}
public void Stop()
{
receiveThread.Abort(new object());
udp.Close();
}
public void ThreadReceive()
{
IPEndPoint ip = new IPEndPoint(IPAddress.Any, PORT_NUMBER);
while (true)
{
var data = udp.Receive(ref ip);
message = Encoding.Default.GetString(data);
}
}
public void Send(string message)
{
UdpClient client = new UdpClient();
IPEndPoint ip = new IPEndPoint(IPAddress.Parse("255.255.255.255"), PORT_NUMBER);
byte[] bytes = Encoding.ASCII.GetBytes(message);
client.Send(bytes, bytes.Length, ip);
client.Close();
}
}