C# 按定时间隔在UDP端口上启动/停止接收数据
我有一个监听特定端口上UDP数据包的函数。每当我收到数据时,我希望函数停止在该端口上接收数据,等待5秒钟,然后继续侦听数据。基本流程是:C# 按定时间隔在UDP端口上启动/停止接收数据,c#,sockets,udp,dispose,C#,Sockets,Udp,Dispose,我有一个监听特定端口上UDP数据包的函数。每当我收到数据时,我希望函数停止在该端口上接收数据,等待5秒钟,然后继续侦听数据。基本流程是: 侦听UDP数据包 接收UDP数据包并对该数据进行任何必要的处理 阻止传入的UDP数据包并等待5秒钟 重复一遍 我有这个功能,但我不知道如何在5秒钟的等待期间阻止UDP数据包。我在UdpClient上使用了EnableBroadcast布尔值,但它没有任何作用。我还尝试将Broadcast和BlockSource的SocketOptionName设置为true/
UdpClient
上使用了EnableBroadcast
布尔值,但它没有任何作用。我还尝试将Broadcast
和BlockSource
的SocketOptionName
设置为true/false,但它也没有任何作用
private async void ReceiveUdpPackets()
{
await Task.Run(async () =>
{
try
{
while (receivePackets)
{
Log.Info("Listening for UDP packets...");
listener.Client.SetSocketOption(SocketOptionLevel.Udp, SocketOptionName.BlockSource, false);
byte[] bytes = listener.Receive(ref groupEP);
listener.Client.SetSocketOption(SocketOptionLevel.Udp, SocketOptionName.BlockSource, true);
Log.Info($"Received UDP broadcast from {groupEP} :");
Log.Info($"{Encoding.ASCII.GetString(bytes, 0, bytes.Length)}");
var bString = BitConverter.ToString(bytes).Replace("-", "");
Log.Info("UDP ByteString: " + bString);
DecodeByteString(bString);
await Task.Delay(5000);
}
}
catch (Exception ex)
{
Log.Error("There was an issue decoding the UDP packet: " + ex.ToString());
}
});
}
如果您希望客户端在等待期间无法发送任何内容,则需要某种方式让他们知道服务器未处于侦听状态。您可以在不同的端口上运行一个单独的任务,客户端可以查询该任务,以查看是否可以在主端口上传输和处理数据。有很多方法可以做到这一点,但基本思想听起来很简单:客户端查询辅助端口,服务器响应一条消息,指示主端口是否“在线”。如果没有,客户机将等待,直到从服务器接收到“继续”。如果是这样,客户机可以立即将其信息发送到服务器上 如果这听起来不吸引人,您还可以在服务器端实现一个数据队列模型。您可以让一个任务用来自客户端的传入数据填充,让另一个线程处理从该源提取的数据。请注意,这不会停止传输,因此它不是解决问题的完美方案,但它确实有几个好处。下面是一个(有缺陷的)代码示例:
使用System.Collections.Concurrent;
Net系统;
使用System.Net.Sockets;
使用System.Threading.Tasks;
名称空间示例名称空间
{
/*
*数据类;封装从客户端接收的字节数组数据。
*在实际实现中,这可能是放置代码的好地方
*以某种方式解释来自客户端的字节
*/
公共级传输
{
公共IPEndPoint客户端{get;set;}
公共字节[]数据{get;set;}
公共传输(IPEndPoint客户端,字节[]数据)
{
客户=客户;
数据=数据;
}
}
公共类服务器
{
私有UdpClient侦听器;
/*
*您可能希望使其成为一个有界集合,以防止
*收藏不要变得太大
*/
private BlockingCollection dataReceived=新建BlockingCollection();
private bool receivePackets=true;
private bool processData=true;
私人互联网端点组;
公共服务器(IPEndPoint listenAt)
{
listener=新的UdpClient(listenAt);
groupEP=listenAt;
}
公开募捐
{
ProcessData();
接收数据();
}
公共异步void ReceiveData()
{
等待任务。运行(()=>{
while(接收数据包)
{
字节[]数据=listener.Receive(ref groupEP);
dataReceived.Add(新传输(groupEP,data));
}
});
}
公共异步void ProcessData()
{
//您可以运行其中的一些来增加处理
//在不改变工作方式的情况下加快速度
等待任务。运行(异步()=>{
while(processData)
{
//块,直到数据可用
传输数据=接收到的数据。Take();
//用数据做事情。。。
等待任务。延迟(5000);
}
});
}
}
}
如上所述,本例存在一些问题-如果您想要实际实现此功能,我强烈建议您将
dataReceived
设置为一个有界的阻塞集合,这样您就不必担心内存问题。另外,通过向Take()和TryTake()调用以及创建的任何线程传递一个消息来关闭整个进程通常也很有用。但是,设计本身应该允许在处理客户端成为性能问题时轻松进行多任务处理。如果您希望客户端在等待期间无法发送任何内容,则需要某种方式让他们知道服务器未处于侦听状态。您可以在不同的端口上运行一个单独的任务,客户端可以查询该任务,以查看是否可以在主端口上传输和处理数据。有很多方法可以做到这一点,但基本思想听起来很简单:客户端查询辅助端口,服务器响应一条消息,指示主端口是否“在线”。如果没有,客户机将等待,直到从服务器接收到“继续”。如果是这样,客户机可以立即将其信息发送到服务器上
如果这听起来不吸引人,您还可以在服务器端实现一个数据队列模型。您可以让一个任务用来自客户端的传入数据填充,让另一个线程处理从该源提取的数据。请注意,这不会停止传输,因此它不是解决问题的完美方案,但它确实有几个好处。下面是一个(有缺陷的)代码示例:
使用System.Collections.Concurrent;
Net系统;
使用System.Net.Sockets;
使用System.Threading.Tasks;
名称空间示例名称空间
{
/*
*数据类;封装从客户端接收的字节数组数据。
*在实际实现中,这可能是放置代码的好地方
*这就解释了字节fr