UDP客户端 - 如何在BeginReceive之后关闭

时间:2018-02-17 19:06:01

标签: sockets udp client

我需要从我的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()?

提前致谢

迈克尔

1 个答案:

答案 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();
    }
}