Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.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#.NET 4.0/4.5 UDP发送问题_C#_.net_Sockets_Networking_Udp - Fatal编程技术网

C#.NET 4.0/4.5 UDP发送问题

C#.NET 4.0/4.5 UDP发送问题,c#,.net,sockets,networking,udp,C#,.net,Sockets,Networking,Udp,我正在用C#编写一个网络库,最初使用的是.NET3.5框架。我最近决定切换到.NET4.5,但开始遇到发送UDP数据包的问题。我遇到的问题是,如果UDP数据包发送得太快,Socket.SendToAsync方法会以AddressFamilyNotSupported的SocketError完成,并且数据包永远不会发送 如果我将项目切换到.NET3.5,无论我多么努力地重复,我都不会遇到这个问题。这也可以在.NET4.0中复制 下面是我为重现这个问题而组织的项目的一个例子。如果对“ClientSnd

我正在用C#编写一个网络库,最初使用的是.NET3.5框架。我最近决定切换到.NET4.5,但开始遇到发送UDP数据包的问题。我遇到的问题是,如果UDP数据包发送得太快,
Socket.SendToAsync
方法会以
AddressFamilyNotSupported
SocketError
完成,并且数据包永远不会发送

如果我将项目切换到.NET3.5,无论我多么努力地重复,我都不会遇到这个问题。这也可以在.NET4.0中复制

下面是我为重现这个问题而组织的项目的一个例子。如果对“ClientSnd”或“ServerSnd”按钮发送垃圾邮件,您将看到出现错误。将项目切换到.NET3.5并发送您想要的垃圾邮件。。。没有问题

在搜索这个问题时,我没有找到多少有用的信息。有什么想法吗

编辑(从演示问题的示例项目中添加代码):

以下是客户端和服务器绑定的位置:

            byte[] clientBuffer = new byte[32768];
            byte[] serverBuffer = new byte[32768];

            IPEndPoint clientLocalEndPoint = GetLocalIPEndPoint(0, AddressFamily.InterNetwork);
            IPEndPoint serverLocalEndPoint = GetLocalIPEndPoint(6337, AddressFamily.InterNetwork);

            m_ClientSocket.ExclusiveAddressUse = true;
            m_ServerSocket.ExclusiveAddressUse = true;
            m_ClientSocket.Bind(clientLocalEndPoint);
            m_ServerSocket.Bind(serverLocalEndPoint);

            m_ClientSendArgs.RemoteEndPoint = GetRemoteIPEndPoint("127.0.0.1", 6337, AddressFamily.InterNetwork);
            m_ClientRecvArgs.RemoteEndPoint = m_ClientSocket.LocalEndPoint;

            m_ServerSendArgs.RemoteEndPoint = GetRemoteIPEndPoint("127.0.0.1", ((IPEndPoint)m_ClientSocket.LocalEndPoint).Port, AddressFamily.InterNetwork);
            m_ServerRecvArgs.RemoteEndPoint = m_ServerSocket.LocalEndPoint;

            m_ClientSendArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnClientCompletion);
            m_ClientRecvArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnClientCompletion);
            m_ServerSendArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnServerCompletion);
            m_ServerRecvArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnServerCompletion);

            m_ClientRecvArgs.SetBuffer(clientBuffer, 0, clientBuffer.Length);
            m_ServerRecvArgs.SetBuffer(serverBuffer, 0, serverBuffer.Length);

            ClientReceive();
            ServerReceive();
由于无论是谁发送数据(客户端还是服务器),都会发生这种情况,因此我将重点关注作为发送者的客户端:

单击
ClientSnd
按钮:

    private void Button_ClientSnd_Click(object sender, RoutedEventArgs e)
    {
        lock (SyncRoot)
        {
            byte[] buffer = Encoding.ASCII.GetBytes("Hello there.  Just testing.  Nothing to see here.  Move along.");

            m_ClientSendQueue.Enqueue(buffer);

            if (!m_ClientTransmitting)
            {
                m_ClientTransmitting = true;

                ClientSendBuffer();
            }
        }
    }
客户端的发送方法:

    private void ClientSendBuffer()
    {
        lock (SyncRoot)
        {
            if (m_ClientSendQueue.Count > 0)
            {
                byte[] buffer = m_ClientSendQueue.Dequeue();

                m_ClientSendArgs.SetBuffer(buffer, 0, buffer.Length);

                ClientSend();
            }
            else
            {
                m_ClientTransmitting = false;
            }
        }
    }

    private void ClientSend()
    {
        if (!m_ClientSocket.SendToAsync(m_ClientSendArgs))
        {
            OnClientCompletion(this, m_ClientSendArgs);
        }
    }
    private void OnClientCompletion(object sender, SocketAsyncEventArgs e)
    {
        SocketError socketError = e.SocketError;

        if (socketError != SocketError.Success)
        {
            ClientConsoleWrite("SocketError: {0}\r\n", socketError);
        }

        switch (e.LastOperation)
        {
            case SocketAsyncOperation.SendTo:
                {
                    if (socketError == SocketError.Success)
                    {
                        ClientConsoleWrite("Client message sent!\r\n");
                    }

                    ClientSendBuffer();

                    break;
                }
            case SocketAsyncOperation.ReceiveFrom:
                {
                    int bytesTransferred = e.BytesTransferred;

                    byte[] buffer = new byte[bytesTransferred];

                    Buffer.BlockCopy(e.Buffer, e.Offset, buffer, 0, bytesTransferred);

                    string message = Encoding.ASCII.GetString(buffer);

                    ClientConsoleWrite("Message received: {0}\r\n", message);

                    ClientReceive();

                    break;
                }
        }
    }
客户端的完成回调:

    private void ClientSendBuffer()
    {
        lock (SyncRoot)
        {
            if (m_ClientSendQueue.Count > 0)
            {
                byte[] buffer = m_ClientSendQueue.Dequeue();

                m_ClientSendArgs.SetBuffer(buffer, 0, buffer.Length);

                ClientSend();
            }
            else
            {
                m_ClientTransmitting = false;
            }
        }
    }

    private void ClientSend()
    {
        if (!m_ClientSocket.SendToAsync(m_ClientSendArgs))
        {
            OnClientCompletion(this, m_ClientSendArgs);
        }
    }
    private void OnClientCompletion(object sender, SocketAsyncEventArgs e)
    {
        SocketError socketError = e.SocketError;

        if (socketError != SocketError.Success)
        {
            ClientConsoleWrite("SocketError: {0}\r\n", socketError);
        }

        switch (e.LastOperation)
        {
            case SocketAsyncOperation.SendTo:
                {
                    if (socketError == SocketError.Success)
                    {
                        ClientConsoleWrite("Client message sent!\r\n");
                    }

                    ClientSendBuffer();

                    break;
                }
            case SocketAsyncOperation.ReceiveFrom:
                {
                    int bytesTransferred = e.BytesTransferred;

                    byte[] buffer = new byte[bytesTransferred];

                    Buffer.BlockCopy(e.Buffer, e.Offset, buffer, 0, bytesTransferred);

                    string message = Encoding.ASCII.GetString(buffer);

                    ClientConsoleWrite("Message received: {0}\r\n", message);

                    ClientReceive();

                    break;
                }
        }
    }

我明白了。之所以出现此问题,是因为变量m_ClientSendArgs上的基础缓冲区一直在使用
SetBuffer
进行更改:

byte[] buffer = m_ClientSendQueue.Dequeue();

m_ClientSendArgs.SetBuffer(buffer, 0, buffer.Length);
当我为其分配静态缓冲区并使用buffer.BlockCopy时,问题消失了:

byte[] buffer = m_ClientSendQueue.Dequeue();

Buffer.BlockCopy(buffer, 0, m_ClientSendBuffer, 0, buffer.Length);

m_ClientSendArgs.SetBuffer(0, buffer.Length);

所以我一直在错误地实施它。奇怪的是,这不是.NET 3.5上的问题,也不是.NET 4.0/4.5上的TCP问题。

请将相关片段发布到您的问题中。许多人没有时间下载、提取和运行示例项目。你能在示例代码中把地址设置在哪里吗?我明白。我在我的问题中发布了相关的代码片段。在GetRemoteIPEndPoint中,您有
catch{}
,为什么要丢弃所有异常?您可能发生了异常,但丢失了该异常,并且正在为地址返回null。删除那个try-catch,看看会出现什么错误。我从我创建的支持库中复制了那个片段,该库实际上处理了异常,但我没有删除try/catch,而是将空的catch留在了那里。我删除了它,但没有什么区别,因为当套接字绑定时会调用一次GetRemoteIPEndPoint。这个问题发生在发送数据“太快”之后,并且只能在.NET 4.0和4.5上重现。我注意到从UI调用它时,它似乎发生了。如果我单击“ClientSnd”按钮,然后按住enter键发送垃圾邮件,则会出现此问题。如果我创建了一个while循环,它发送缓冲区10000次,然后单击“ClientSnd”按钮一次(新while循环所在的位置),它就可以正常工作。如果我再次单击该按钮并再次发送10000次缓冲区,它将失败。