问题描述
正如标题所说我有一个问题,UDP在C#。我试图建立一个图书馆的游戏DayZ的RCON协议。
我的问题是,我不接受每一个数据包,我应该接受。发送命令后,服务器回复一个分裂的答案。该分组头包含的总数据包数和当前分组的索引。现在,如果我应该得到17包我只得到我的应用程序8-15包。
使用Wireshark的测试后,我现在所有的包到我的电脑上知道的。他们只是不得到我的应用程序或类似的东西的认可。
我的实际问题是:是否有可能以prevent我的网卡和我的应用程序之间失去了包?要么为什么会发生呢?
下面是我目前的code。它的pretty的肮脏的,因为我工作不正常后,撕开它除了:
专用插座_udpClient;
私人螺纹_receiverThread;
私人螺纹_workerThread;
专用队列和LT; byte []的> _packetQueue;
私人PacketBuffer [] MessageBuffer;
专用字节SenderSequence = 0;
私人IPEndPoint连接;
公共RCON(ip地址IP,INT端口)
{
连接=新IPEndPoint(IP,端口);
_udpClient =新的Socket(connection.Address.AddressFamily,SocketType.Dgram,ProtocolType.Udp);
_udpClient.Connect(连接);
MessageBuffer =新PacketBuffer [256];
_packetQueue =新问答LT; byte []的>();
_receiverThread =新主题(新的ThreadStart(ReceiveCallback));
_receiverThread.IsBackground = TRUE;
_receiverThread.Priority = ThreadPriority.AboveNormal;
_receiverThread.Start();
_workerThread =新主题(新的ThreadStart(WorkerCallback));
_workerThread.IsBackground = TRUE;
_workerThread.Start();
}
公共无效登录(字符串密码)
{
LoginPacket包=新LoginPacket(密码);
_udpClient.Send(packet.Bytes);
}
公共无效SendCommand(字符串命令)
{
CommandPacket包=新CommandPacket(SenderSequence,命令);
SenderSequence ++;
_udpClient.Send(packet.Bytes);
}
私人无效ReceiveCallback()
{
而(真)
{
byte []的缓冲区=新的字节[1036];
如果(_udpClient.Receive(缓冲液)大于0)
_packetQueue.Enqueue(缓冲液);
}
}
私人无效WorkerCallback()
{
而(真)
{
如果(_packetQueue.Count大于0)
{
byte []的缓冲区= _packetQueue.Dequeue();
如果(缓冲!= NULL)
{
尝试
{
分组receivedPacket = Packet.ParseIncoming(缓冲液);
OnPacketReceived(新PacketReceivedEventArgs(receivedPacket));
开关(receivedPacket.Type)
{
案例PacketType.Message:
OnMessageReceived(新MessageReceivedEventArgs(receivedPacket.Content));
MessageCallbackPacket包=新MessageCallbackPacket(receivedPacket.SequenceNumber);
_udpClient.Send(packet.Bytes);
打破;
案例PacketType.CommandCallback:
如果(MessageBuffer [receivedPacket.SequenceNumber] == NULL)
MessageBuffer [receivedPacket.SequenceNumber] =新PacketBuffer(receivedPacket);
其他
MessageBuffer [receivedPacket.SequenceNumber] .AddPacket(receivedPacket);
如果(MessageBuffer [receivedPacket.SequenceNumber] .IsComplete)
OnCommandCallback(新CommandCallbackEventArgs(MessageBuffer [receivedPacket.SequenceNumber] .GetContent()));
打破;
}
}
赶上(ArgumentException的){}
赶上(发生OverflowException){}
赶上(出现FormatException){}
}
}
}
}
这通常是因为你不占用你的数据报速度不够快,所以在内核套接字缓冲区满和网络堆栈开始下降新到达的数据包。一些要点:
- 增加接收缓冲区插座上,
- 请不要购买在每次迭代锁 - 多读就可以了,然后把数据放入队列,
- 在考虑无阻塞的方式,而不是线程。
As the title says I have a problem with UDP in C#.I'm trying to build a library for the rcon protocol of the game DayZ.
My problem is that I dont receive every packet I should receive.After sending a command the server replies with an split answer. The packet header contains the total packet count and the index of the current packet.Now if I should get 17 packets I only get 8-15 packets in my application.
After testing with WireShark I know now that all packages arrive on my computer. They just dont get recognized by my application or something like that.
My Actual Question is:Is it possible to prevent losing the packages between my network card and my application? orWhy does that happen?
Here is my current code. Its pretty dirty because I ripped it apart after not working as expected:
private Socket _udpClient;
private Thread _receiverThread;
private Thread _workerThread;
private Queue<byte[]> _packetQueue;
private PacketBuffer[] MessageBuffer;
private byte SenderSequence = 0;
private IPEndPoint connection;
public RCon(IPAddress ip, int port)
{
connection = new IPEndPoint(ip, port);
_udpClient = new Socket(connection.Address.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
_udpClient.Connect(connection);
MessageBuffer = new PacketBuffer[256];
_packetQueue = new Queue<byte[]>();
_receiverThread = new Thread(new ThreadStart(ReceiveCallback));
_receiverThread.IsBackground = true;
_receiverThread.Priority = ThreadPriority.AboveNormal;
_receiverThread.Start();
_workerThread = new Thread(new ThreadStart(WorkerCallback));
_workerThread.IsBackground = true;
_workerThread.Start();
}
public void Login(string password)
{
LoginPacket packet = new LoginPacket(password);
_udpClient.Send(packet.Bytes);
}
public void SendCommand(string command)
{
CommandPacket packet = new CommandPacket(SenderSequence, command);
SenderSequence++;
_udpClient.Send(packet.Bytes);
}
private void ReceiveCallback()
{
while (true)
{
byte[] buffer = new byte[1036];
if (_udpClient.Receive(buffer) > 0)
_packetQueue.Enqueue(buffer);
}
}
private void WorkerCallback()
{
while (true)
{
if (_packetQueue.Count > 0)
{
byte[] buffer = _packetQueue.Dequeue();
if (buffer != null)
{
try
{
Packet receivedPacket = Packet.ParseIncoming(buffer);
OnPacketReceived(new PacketReceivedEventArgs(receivedPacket));
switch (receivedPacket.Type)
{
case PacketType.Message:
OnMessageReceived(new MessageReceivedEventArgs(receivedPacket.Content));
MessageCallbackPacket packet = new MessageCallbackPacket(receivedPacket.SequenceNumber);
_udpClient.Send(packet.Bytes);
break;
case PacketType.CommandCallback:
if (MessageBuffer[receivedPacket.SequenceNumber] == null)
MessageBuffer[receivedPacket.SequenceNumber] = new PacketBuffer(receivedPacket);
else
MessageBuffer[receivedPacket.SequenceNumber].AddPacket(receivedPacket);
if (MessageBuffer[receivedPacket.SequenceNumber].IsComplete)
OnCommandCallback(new CommandCallbackEventArgs(MessageBuffer[receivedPacket.SequenceNumber].GetContent()));
break;
}
}
catch (ArgumentException) { }
catch (OverflowException) { }
catch (FormatException) { }
}
}
}
}
This is usually because you are not consuming your datagrams fast enough, so in-kernel socket buffer gets full and the network stack starts dropping newly arriving packets. Some points:
- Increase the receive buffer on the socket,
- Don't acquire locks on every iteration - read as much as you can, then put data into the queue,
- Consider non-blocking approach instead of threads.
这篇关于C#UDP packetloss虽然所有的数据包到达(Wireshark的)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!