UDP receivefrom 或 sendto 不工作

UDP receivefrom or sendto not working

我正在学习如何对网络进行编程。我正在尝试使用套接字而不是 udpclient class 创建一个 udp 系统(我通过搜索找不到太多信息)。

服务器从客户端接收消息并打印它们,但客户端卡在 receivefrom 上,它阻塞了线程。 我在这里做错了什么?

我的服务器代码:

Socket sck = new Socket( AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp );

IPEndPoint _IPEndPoint = new IPEndPoint( IPAddress.Any, 55566 );
EndPoint _EndPoint = _IPEndPoint;
sck.Bind( _IPEndPoint );

byte[] buffer = new byte[ 255 ];
int rec = sck.ReceiveFrom( buffer, 0, buffer.Length, SocketFlags.None, ref _EndPoint );
Array.Resize( ref buffer, rec );
string clientIP = Encoding.Default.GetString( buffer );
Console.WriteLine( "Received: {0}", clientIP );

buffer = new byte[ 255 ];
rec = sck.ReceiveFrom( buffer, 0, buffer.Length, SocketFlags.None, ref _EndPoint );
Array.Resize( ref buffer, rec );
int clientPort = BitConverter.ToInt32( buffer, 0 );
Console.WriteLine( "Received: {0}", clientPort );

buffer = Encoding.Default.GetBytes( "Hello " + clientIP );
sck.SendTo( buffer, 0, buffer.Length, SocketFlags.None, new IPEndPoint(IPAddress.Parse(clientIP), clientPort) ); // never gets received

sck.Close();


Process.GetCurrentProcess().WaitForExit();

和客户端代码:

Socket sck = new Socket( AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp );
IPEndPoint ipEndPoint = new IPEndPoint( IPAddress.Parse( "127.0.0.1" ), 55566 );
sck.Bind( new IPEndPoint( IPAddress.Parse( "127.0.0.1" ), 0 ) );
EndPoint endPoint = ipEndPoint;

string msg = new Func<string>( () =>
{
    var host = Dns.GetHostEntry( Dns.GetHostName() );
    foreach ( var ip in host.AddressList )
    {
        if ( ip.AddressFamily == AddressFamily.InterNetwork )
        {
            return ip.ToString();
        }
    }
    throw new Exception( "Local IP Address Not Found!" );
} )();
byte[] msgBuffer = Encoding.Default.GetBytes( msg );
Console.WriteLine( "sending IP" );
sck.SendTo( msgBuffer, 0, msgBuffer.Length, SocketFlags.None, ipEndPoint );

msgBuffer = BitConverter.GetBytes( ( (IPEndPoint) sck.LocalEndPoint ).Port );
Console.WriteLine( "sending port" );
sck.SendTo( msgBuffer, 0, msgBuffer.Length, SocketFlags.None, ipEndPoint );

byte[] buffer = new byte[ 255 ];
Console.WriteLine( "receiving message" );
int rec = sck.ReceiveFrom( buffer, 0, buffer.Length, SocketFlags.None, ref endPoint ); // gets stuck here

Array.Resize( ref buffer, rec );

Console.WriteLine( "Received: " + Encoding.Default.GetString( buffer ) );

sck.Close();

如果不进一步了解您正在测试的环境,就不可能肯定地说。但最有可能的是,客户端发送了错误的 IP 地址 and/or 端口。

无论如何,服务器都不应该依赖客户端本身来报告其地址。服务器将知道来自 ReceiveFrom() 方法的信息,并且应该 使用来自该方法的信息发送回数据。

例如:

EndPoint clientEndPoint = new IPEndPoint(IPAddress.Any, 0);

rec = sck.ReceiveFrom( buffer, 0, buffer.Length, SocketFlags.None, ref clientEndPoint);
Array.Resize( ref buffer, rec );
int clientPort = BitConverter.ToInt32( buffer, 0 );
Console.WriteLine( "Received: {0}", clientPort );

buffer = Encoding.Default.GetBytes( "Hello " + clientIP );
sck.SendTo( buffer, 0, buffer.Length, SocketFlags.None, clientEndPoint); // never gets received

当然,请记住 UDP 是不可靠的。使用 UDP 时,以下所有情况均成立:

  1. 任何给定的数据报可能永远不会到达。
  2. 任何给定的数据报都可能被多次接收。
  3. 发送的数据报可能以任何顺序到达,无论它们的发送顺序如何。

自然地,这些特征可能会对您编写的代码造成严重破坏,其中代码假定数据将以某种特定顺序发送和接收,并且没有任何重新排列或重复。