gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 12:00:59 35 4
gpt4 key购买 nike

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

如果我将项目切换到 .NET 3.5,无论我多么努力地重复它,我都不会遇到这个问题。这也可以在 .NET 4.0 中重现。

这是 link到我放在一起重现这个问题的项目。如果您向“ClientSnd”或“ServerSnd”按钮发送垃圾邮件,您将看到错误发生。将项目切换到 .NET 3.5 并随心所欲地发送垃圾邮件……完全没有问题。

我一直无法找到很多有用的信息搜索这个问题。有任何想法吗?

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

这是客户端和服务器都发生绑定(bind)的地方:

            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();
GetRemoteIPEndPointGetLocalIPEndPoint方法:
    private static IPEndPoint GetRemoteIPEndPoint(string address, int port, AddressFamily addressFamily)
{
IPAddress[] ipAddresses = null;

ipAddresses = Dns.GetHostAddresses(address);

List<IPEndPoint> ipEndPointList = new List<IPEndPoint>();

for (int i = 0; i < ipAddresses.Length; i++)
{
IPAddress ipAddress = ipAddresses[i];

if (ipAddress.AddressFamily == addressFamily)
{
IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, port);

ipEndPointList.Add(ipEndPoint);
}
}

return ipEndPointList.ToArray()[0];
}

private static IPEndPoint GetLocalIPEndPoint(int port, AddressFamily addressFamily)
{
IPEndPoint localEndPoint = null;

switch (addressFamily)
{
case AddressFamily.InterNetwork:
{
localEndPoint = new IPEndPoint(IPAddress.Any, port);

break;
}
case AddressFamily.InterNetworkV6:
{
localEndPoint = new IPEndPoint(IPAddress.IPv6Any, port);

break;
}
}

return localEndPoint;
}

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

点击 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;
}
}
}

最佳答案

我想通了。发生此问题是因为变量 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 问题。

关于C# .NET 4.0/4.5 UDP 发送问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15485999/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com