我有一个在特定端口上侦听UDP数据包的功能。每当我接收到数据时,我都希望函数停止在该端口上接收数据,等待5秒钟,然后继续侦听数据。基本流程是:
我可以使用该功能,但是我无法弄清楚如何在5秒的等待期内阻止UDP数据包。我在<script>$(document).ready(function() {$.getScript("assets/js/main.js");});</script>
上使用了EnableBroadcast
布尔值,但是它什么也没做。我还尝试将UdpClient
和SocketOptionName
的{{1}}设置为true / false,它也没有任何作用。
Broadcast
答案 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()调用以及您创建的任何线程来关闭整个过程通常也很有用。但是,在处理客户端成为性能问题的情况下,设计本身应该允许轻松的多任务处理。