Jump to content

  • Log In with Google      Sign In   
  • Create Account


#ActualMorxeton

Posted 18 March 2013 - 04:13 PM

Hello,

 

I am working on writing a network library in C# and originally had used the .NET 3.5 Framework.  I recently decided to switch to .NET 4.5 but started running into an issue with sending UDP packets.  What I'm running into is if UDP packets are sent too fast, the Socket.SendToAsync method completes with a SocketError of AddressFamilyNotSupported and the packets are never sent.  If I switch the project to .NET 3.5, I never run into the issue no matter how hard I try to repeat it.  This also can be reproduced in .NET 4.0.

 

I attached a project I put together to reproduce the issue.  If you spam the "ClientSnd" or "ServerSnd" buttons you'll see the error occur.  Switch the project to .NET 3.5 and spam all you want... no issues at all.

 

I haven't been able to find much useful information googling this issue.  Any ideas?

 

EDIT (added code from the sample project demoing the issue):

 

Here's where the binds are happening for both the client and server:

 

 

 

                
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();
 

 

 

The GetRemoteIPEndPoint and GetLocalIPEndPoint methods:

 

 

 

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;

} 

 

Since this happens regardless of who sends the data (client or server), I'll focus on the client being the sender:

 

Clicking the ClientSnd button:

 

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();                
		}            
	}
} 

 

 

Sending methods for the client:

 

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);            
	}
} 

 

Completion callback for the client:

 

 

 

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

#2Morxeton

Posted 18 March 2013 - 04:12 PM

Hello,

 

I am working on writing a network library in C# and originally had used the .NET 3.5 Framework.  I recently decided to switch to .NET 4.5 but started running into an issue with sending UDP packets.  What I'm running into is if UDP packets are sent too fast, the Socket.SendToAsync method completes with a SocketError of AddressFamilyNotSupported and the packets are never sent.  If I switch the project to .NET 3.5, I never run into the issue no matter how hard I try to repeat it.  This also can be reproduced in .NET 4.0.

 

I attached a project I put together to reproduce the issue.  If you spam the "ClientSnd" or "ServerSnd" buttons you'll see the error occur.  Switch the project to .NET 3.5 and spam all you want... no issues at all.

 

I haven't been able to find much useful information googling this issue.  Any ideas?

 

EDIT (added code from the sample project demoing the issue):

 

Here's where the binds are happening for both the client and server:

 

 

 

                
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();
 

 

 

The "GetRemoteIPEndPoint" and "GetLocalIPEndPoint" methods:

 

 

 

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;

} 

 

Since this happens regardless of who sends the data (client or server), I'll focus on the client being the sender:

 

Clicking the "ClientSnd" button:

 

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();                
		}            
	}
} 

 

 

Sending methods for the client:

 

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);            
	}
} 

 

Completion callback for the client:

 

 

 

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

 


#1Morxeton

Posted 18 March 2013 - 11:08 AM

Hello,

 

I am working on writing a network library in C# and originally had used the .NET 3.5 Framework.  I recently decided to switch to .NET 4.5 but started running into an issue with sending UDP packets.  What I'm running into is if UDP packets are sent too fast, the Socket.SendToAsync method completes with a SocketError of AddressFamilyNotSupported and the packets are never sent.  If I switch the project to .NET 3.5, I never run into the issue no matter how hard I try to repeat it.  This also can be reproduced in .NET 4.0.

 

I attached a project I put together to reproduce the issue.  If you spam the "ClientSnd" or "ServerSnd" buttons you'll see the error occur.  Switch the project to .NET 3.5 and spam all you want... no issues at all.

 

I haven't been able to find much useful information googling this issue.  Any ideas?


PARTNERS