Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#UDP数据包在所有数据包到达时丢失(WireShark)_C#_.net_Networking_Udp - Fatal编程技术网

C#UDP数据包在所有数据包到达时丢失(WireShark)

C#UDP数据包在所有数据包到达时丢失(WireShark),c#,.net,networking,udp,C#,.net,Networking,Udp,正如标题所说,我在C#中遇到了UDP问题。 我正试图为DayZ游戏的rcon协议建立一个库 我的问题是我没有收到我应该收到的每一个包裹。 发送命令后,服务器会以拆分应答进行回复。数据包头包含数据包总数和当前数据包的索引。 现在,如果我得到17个数据包,我的应用程序中只得到8-15个数据包 在使用WireShark进行测试后,我现在知道所有软件包都已到达我的计算机。他们只是没有得到我的申请或类似的东西的认可 我的实际问题是: 是否可以防止丢失网卡和应用程序之间的软件包?或 为什么会这样 这是我目前

正如标题所说,我在C#中遇到了UDP问题。 我正试图为DayZ游戏的rcon协议建立一个库

我的问题是我没有收到我应该收到的每一个包裹。 发送命令后,服务器会以拆分应答进行回复。数据包头包含数据包总数和当前数据包的索引。 现在,如果我得到17个数据包,我的应用程序中只得到8-15个数据包

在使用WireShark进行测试后,我现在知道所有软件包都已到达我的计算机。他们只是没有得到我的申请或类似的东西的认可

我的实际问题是: 是否可以防止丢失网卡和应用程序之间的软件包?或 为什么会这样

这是我目前的代码。它很脏,因为我在没有按预期工作后把它撕开了:

    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) { }
                }
            }
        }
    }
private Socket\u udpClient;
私有线程_receiverThread;
私有线程\u workerThread;
专用队列_packetQueue;
私有PacketBuffer[]消息缓冲区;
专用字节发送器顺序=0;
专用iEndpoint连接;
公共RCon(ip地址ip,int端口)
{
连接=新的IPEndPoint(ip,端口);
_udpClient=新套接字(connection.Address.AddressFamily,SocketType.Dgram,ProtocolType.Udp);
_udpClient.Connect(连接);
MessageBuffer=newpacketbuffer[256];
_packetQueue=新队列();
_ReceiveThread=新线程(新线程开始(ReceiveCallback));
_receiverThread.IsBackground=true;
_receiverThread.Priority=ThreadPriority.Overnormal;
_receiverThread.Start();
_workerThread=新线程(新线程开始(WorkerCallback));
_workerThread.IsBackground=true;
_workerThread.Start();
}
公共无效登录(字符串密码)
{
LoginPacket数据包=新的LoginPacket(密码);
_udpClient.Send(packet.Bytes);
}
公共void SendCommand(字符串命令)
{
CommandPacket数据包=新的CommandPacket(发送者顺序,命令);
SenderSequence++;
_udpClient.Send(packet.Bytes);
}
私有void ReceiveCallback()
{
while(true)
{
字节[]缓冲区=新字节[1036];
如果(_udpClient.Receive(buffer)>0)
_packetQueue.Enqueue(缓冲区);
}
}
私有void WorkerCallback()
{
while(true)
{
如果(_packetQueue.Count>0)
{
字节[]缓冲区=_packetQueue.Dequeue();
if(缓冲区!=null)
{
尝试
{
Packet receivedPacket=Packet.ParseIncoming(缓冲区);
OnPacketReceived(新PacketReceivedEventArgs(receivedPacket));
开关(接收分组型)
{
箱子包装类型。信息:
OnMessageReceived(新消息receivedeventargs(receivedPacket.Content));
MessageCallbackPacket=newmessagecallbackpacket(receivedPacket.SequenceNumber);
_udpClient.Send(packet.Bytes);
打破
case PacketType.CommandCallback:
if(MessageBuffer[receivedPacket.SequenceNumber]==null)
MessageBuffer[receivedPacket.SequenceNumber]=新的PacketBuffer(receivedPacket);
其他的
MessageBuffer[receivedPacket.SequenceNumber].AddPacket(receivedPacket);
if(MessageBuffer[receivedPacket.SequenceNumber].IsComplete)
OnCommandCallback(新命令CallbackEventArgs(MessageBuffer[receivedPacket.SequenceNumber].GetContent());
打破
}
}
捕获(参数异常){}
捕获(溢出例外){}
捕获(格式化异常){}
}
}
}
}

这通常是因为您使用数据报的速度不够快,所以内核套接字缓冲区已满,网络堆栈开始丢弃新到达的数据包。有几点:

  • 增加套接字上的接收缓冲区
  • 不要在每次迭代中获取锁-尽可能多地读取,然后将数据放入队列
  • 考虑非阻塞方法,而不是线程

我总是惊讶于有多少聪明人不知道“loose”和“lose”不是同一个词。感谢你帮助我提高英语知识。
\u udpClient.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReceiveBuffer,一个像0x40000这样的大值)增加接收缓冲区对我有效。非阻塞是指开始接收和结束接收,对吗?我以前用过,但为了测试的目的,我改用了线程。谢谢你的帮助!不,我指的是非阻塞套接字和线程。NET异步回调在线程池中运行。从哪里可以确认接收缓冲区是实际问题?我正在使用默认缓冲区大小为8 KB的WS-2016,并将缓冲区大小增加到2 MB,但这对我的情况没有任何影响。@Girish,检查Socket.Available属性并确保它比缓冲区大小小得多