Я работаю над написанием сетевой библиотеки на C# и изначально использовал .NET 3.5 Framework. Недавно я решил переключиться на .NET 4.5, но столкнулся с проблемой отправки пакетов UDP. То, что я натолкнулся на то, что UDP-пакеты отправляются слишком быстро, метод Socket.SendToAsync
завершает работу с SocketError
AddressFamilyNotSupported
и пакеты никогда не отправляются.C# .NET 4.0/4.5 Ошибка отправки UDP
Если я переключу проект на .NET 3.5, я никогда не сталкиваюсь с проблемой, как бы я ни старался повторить ее. Это также можно воспроизвести в .NET 4.0.
Вот link к проекту, который я собрал, чтобы воспроизвести проблему. Если вы спамете кнопки «ClientSnd» или «ServerSnd», вы увидите ошибку. Переключите проект на .NET 3.5 и спам, который вы хотите ... никаких проблем.
Я не смог найти много полезной информации в этом вопросе. Есть идеи?
EDIT (добавлен код из примера проекта записи демо вопрос):
Вот где связывает происходят и для клиента и сервера:
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();
В GetRemoteIPEndPoint
и GetLocalIPEndPoint
методы:
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;
}
Поскольку это происходит, регар dless кто отправляет данные (клиента или сервера), я сосредоточусь на клиенте является отправитель:
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;
}
}
}
Не могли бы вы разместить соответствующие фрагменты на свой вопрос. У многих людей нет времени на загрузку, извлечение и запуск примерного проекта. В основном вы можете указать, где вы указываете адрес в вашем примере кода? –
Я понимаю. Я опубликовал соответствующие фрагменты моего вопроса. –
в GetRemoteIPEndPoint у вас есть 'catch {}', почему вы выбрасываете все свои исключения? Вероятно, вы совершили исключение, пропустили его и вернули null для адреса. Удалите этот try-catch и посмотрите, какую ошибку вы получите. –