考虑一下代码:
class UPDServer {
//start listener
public void start() {
UdpClient listener = new UdpClient(this._porta);
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 10000);
State s = new State();
s.listener = listener;
s.ipEndPoint = ipEndPoint;
// begin to listen again
listener.BeginReceive(new AsyncCallback(ReceiveCallback), s);
}
//receive data
public void ReceiveCallback(IAsyncResult ar)
{
// we got data
State s = (State)(ar.AsyncState);
Byte[] received = e.escuta.EndReceive(ar, ref e.ipEndPoint);
string text = ""; = Encoding.ASCII.GetString(received);
// ... do somenthing with text
// begin to listen again
s.listener.BeginReceive(new AsyncCallback(ReceiveCallback), e);
}
}
在上面的代码中,EndReceive和下一个BeginReceive之间有一段时间跨度没有人正在收听,我想如果在这个时间跨度中有消息,它将会丢失.
好吧,我想有一些缓冲区,但即便如此,如果缓冲区在没有人正在侦听消息的时间跨度内填满,则消息将丢失.
我记得有人说通过在相同的端点上多次调用BeginReceive可以很简单地解决这个问题,所以我尝试了这个:
for( int x = 0; x < 5;x++) {
escuta.BeginReceive(new AsyncCallback(ReceiveCallback), e);
}
奇怪的是,在同一个套接字上调用begin receive不会抛出错误,但每次收到一条消息时,所有五个beginReceive会触发,并且所有五个都收到相同的消息.
有没有办法改进代码?
最佳答案 首先,无法保证在使用UDP时您将获得所有数据,因此无论如何都必须使您的代码/协议容错.
除非你的处理非常密集,并且你期望大量数据泛滥,否则你可能不需要做不同的事情.只需添加一些错误检测代码,这样您就可以知道代码是否无法应对.
但是,如果需要快速保持接收循环,则在接收数据时,将其复制到队列中以便处理另一个线程,以便您可以快速重新开始读取.或者在某些情况下,您可以编写终端接收,以便在多个数据包背靠背时可以处理重入.