2016-05-16 2 views
1

Я просто изучаю, как программировать сети. Я пытаюсь сделать систему udp, используя сокеты вместо класса udpclient (что-то, что я не мог найти много информации при поиске).UDP receivefrom или sendto не работает

Сервер получает сообщения от клиента и распечатывает их, но клиент застревает в getfrom, где он блокирует поток. Что я здесь делаю неправильно?

Мой код сервера: Код

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

ответ

0

Это невозможно сказать наверняка, не зная больше о среде, в которой вы тестируете. Но, скорее всего, клиент отправляет неверный IP-адрес и/или порт.

Сервер никогда не должен полагаться на самого клиента, чтобы сообщать о его адресе в любом случае. Сервер будет знать эту информацию из метода 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. Переданные датаграммы могут поступать в любом порядке, независимо от того, в каком порядке они были отправлены.

Естественно, эти характеристики могут привести к хаосу с кодом, как то, что вы написали, где код предполагает, что данные будут отправлены и получены в определенном порядке и без каких-либо переупорядочений или дублирования.

Смежные вопросы