在C#中接收最新的UDP数据包

3
我正在使用Unity来可视化一个模拟,其中来自Simulink的数据通过UDP数据包发送到它。我遇到的问题源于Simulink发送UDP数据包的速率和Unity脚本尝试从UDP客户端接收数据的速率不同步。
对于我的Unity脚本,我创建了一个线程,执行一个简单的函数,其中包含一个while循环并在相同的时间间隔内休眠,以使客户端超时(这个时间是我任意设置的)。
public void Start() {
    //  Setup listener.
    this.mSenderAddress = IPAddress.Parse("127.0.0.1");
    this.mSender = new IPEndPoint(this.mSenderAddress, 30001);

    //  Setup background UDP listener thread.
    this.mReceiveThread = new Thread(new ThreadStart(ReceiveData));
    this.mReceiveThread.IsBackground = true;
    this.mReceiveThread.Start();
}

//  Function to receive UDP data.
private void ReceiveData() {
    try {
        //  Setup UDP client.
        this.mClient = new UdpClient(30001);
        this.mClient.Client.ReceiveTimeout = 250;

        //  While thread is still alive.
        while(Thread.CurrentThread.IsAlive) {
            try {
                //  Grab the data.
                byte[] data = this.mClient.Receive(ref this.mSender);

                //  Convert the data from bytes to doubles.
                double[] convertedData = new double[data.Length / 8];
                for(int ii = 0; ii < convertedData.Length; ii++)
                    convertedData[ii] = BitConverter.ToDouble(data, 8 * ii);

                //  DO WHATEVER WITH THE DATA

                //  Sleep the thread.
                Thread.Sleep(this.mClient.Client.ReceiveTimeout);
            } catch(SocketException e) {
                continue;
            }
        }
    } catch(Exception e) {
        Debug.Log(e.ToString());
    }
}

在这里,如果超时/等待时间大于Simulink发送UDP数据包的时间差,则我的可视化将落后于模拟,因为它将读取已发送的下一个数据包而不是最后一个。这是将数据包视为队列的问题。
有没有办法只从接收到的最后一个数据包中获取数据?我知道至少有一种方法可以解决这个问题,因为如果我使用一个采样时间等于或大于UdpClient超时时间的速率传输块,它将起作用;但我希望它比那更加健壮。
由于我的数据包包含有关模拟状态的完整信息(位置、方向、时间等),因此即使我从中间数据包中不使用数据,也无所谓;只要获得最新的数据,即来自最后一个数据包。

我不明白为什么你需要超时。为什么不直接接收Simulink发送的所有数据,直到发送方超时? - Prahlad Yeri
1
receive() 函数获取整个数据流,而不仅仅是单个或少量的数据包。但由于接收到的整个数据可能非常大,因此每次 receive() 调用仅获取由缓冲区大小定义的有限数量的数据。因此,您必须不断调用 receive() 函数,直到缓冲区中剩余的数据为零。 - Prahlad Yeri
1
并且不需要在中间进行睡眠或超时操作,因为这显然会在程序休眠期间导致缓冲区溢出。在那种情况下,超过缓冲区大小的数据包将被忽略或者换句话说,丢失。 - Prahlad Yeri
1
另外,由于您正在使用空白的continue; 而没有检查套接字发生了什么类型的异常,因此在完成工作后,您必须格外小心地中止此线程。否则,那可能会导致CPU计数器飙升! - Prahlad Yeri
1
早就想到了。我的OnApplicationQuit方法已经非常小心地处理了线程。 :) - celestialorb
显示剩余2条评论
1个回答

0

UDP是不可靠的,数据包不能保证按照发送顺序接收。我的建议是使用TCP或在数据包头中放置某种序列号,并继续读取UDP数据包并仅选择最新的数据包。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接