定时间隔开始/停止在UDP端口上接收数据

时间:2019-05-29 22:41:43

标签: c# sockets udp dispose

我有一个在特定端口上侦听UDP数据包的功能。每当我接收到数据时,我都希望函数停止在该端口上接收数据,等待5秒钟,然后继续侦听数据。基本流程是:

  1. 收听UDP数据包。
  2. 接收UDP数据包并对该数据进行任何必要的处理。
  3. 阻止传入的UDP数据包并等待5秒钟。
  4. 重复。

我可以使用该功能,但是我无法弄清楚如何在5秒的等待期内阻止UDP数据包。我在<script>$(document).ready(function() {$.getScript("assets/js/main.js");});</script> 上使用了EnableBroadcast布尔值,但是它什么也没做。我还尝试将UdpClientSocketOptionName的{​​{1}}设置为true / false,它也没有任何作用。

Broadcast

1 个答案:

答案 0 :(得分:0)

如果您希望客户端在等待期间无法发送任何内容,则需要某种方式让他们知道服务器未处于侦听状态。您可以在其他端口上运行单独的任务,客户端可以查询该任务以查看是否可以在主端口上传输和处理数据。有很多方法可以解决此问题,但基本思路很简单:客户端查询辅助端口,服务器响应,并显示一条消息,指示主要端口是否“在线”。如果不是,则客户端等待直到它从服务器接收到批准。如果是这样,客户端可以立即发送其信息。

如果这听起来不那么吸引人,那么您还可以在服务器端实现数据排队模型。您可以让一个任务用来自客户端的传入数据填充BlockingCollection,并用另一个线程处理从该源提取的数据。请注意,这不会停止传输,因此它不是解决您的问题的理想方法,但是它确实有很多好处。这是代码看起来像的一个(有缺陷的)示例:

using System.Collections.Concurrent;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;

namespace ExampleNamespace
{

    /* 
     * data class; encapsulates byte array data received from a client. 
     * in an actual implementation this might be a nice spot to put code 
     * that interprets bytes from the client in some way
     */
    public class Transmission
    {
        public IPEndPoint Client { get; set; }

        public byte[] Data { get; set; }

        public Transmission(IPEndPoint client, byte[] data)
        {
            Client = client;
            Data = data;
        }
    }

    public class Server
    {
        private UdpClient listener;

        /*
         * you probably want to make this a bounded collection to prevent the
         * collection from getting too big
         */
        private BlockingCollection<Transmission> dataReceived = new BlockingCollection<Transmission>();

        private bool receivePackets = true;

        private bool processData = true;

        private IPEndPoint groupEP;

        public Server(IPEndPoint listenAt)
        {
            listener = new UdpClient(listenAt);
            groupEP = listenAt;
        }

        public void Run()
        {
            ProcessData();
            ReceiveData();
        }

        public async void ReceiveData()
        {
            await Task.Run(() => {
                while (receivePackets)
                {
                    byte[] data = listener.Receive(ref groupEP);
                    dataReceived.Add(new Transmission(groupEP, data));
                }
            });
        }

        public async void ProcessData()
        {
            //you could run just a few of these to increase your processing 
            //speed without changing how things work
            await Task.Run(async () => {
                while (processData)
                {
                    //blocks until data is available
                    Transmission data = dataReceived.Take();

                    //do things with the data...

                    await Task.Delay(5000);
                }
            });
        }
    }
}

如前所述,该示例存在一些问题-如果您想真正实现此目标,我强烈建议您考虑使dataReceived成为有界阻塞集合,这样您就不必担心内存问题。同样,通过将CancellationToken传递给Take()和TryTake()调用以及您创建的任何线程来关闭整个过程通常也很有用。但是,在处理客户端成为性能问题的情况下,设计本身应该允许轻松的多任务处理。