Не могу подключиться к собственному приложению TCP-сервера IPv6, работающему в Ubuntu с моно

Моя тестовая инфраструктура состоит из 3 машин: 1 физической машины с Windows 10, работающей под управлением HyperV и 2 виртуальных машины с установленной ОС Ubuntu. Существует полное сетевое соединение между всеми машинами (они проверяют друг друга). Я написал 2 простые программы на C#: TCP-клиент и TCP-сервер (ниже я приложил минимальный код, который воспроизводит проблему). Когда я запускаю клиент на машине с Windows и сервер на одной из машин с Ubuntu, все работает хорошо. Однако, когда я пытаюсь запустить клиент на одном из компьютеров с Ubuntu, а сервер на другом компьютере с Ubuntu, я получаю сообщение об ошибке на стороне клиента:

Информация TCPClientTest.exe: 0: System.Net.Sockets.SocketException (0x80004005): недопустимые аргументы в System.Net.Sockets.TcpClient.Connect (System.Net.IPAddress[] ipAddresses, порт System.Int32) [0x000e9] в <0x000e9] в <<59be416de143456b88b9988284f43350>:0 в System.Net.Sockets.TcpClient.Connect (имя хоста System.String, порт System.Int32) [0x00007] в <59be416de143456b88b9988284f43350>: 0 в хосте System.Net.Cort.Cen, Порт System.Int32) [0x00006] в <59be416de143456b88b9988284f43350>: 0 в TCPClientTest.Program.Main (аргументы System.String[]) [0x00002] в: 0 DateTime = 2016-11-09T21: 25: 42.4641950Z

TCP-клиент:

TcpClient client = new TcpClient("fe80::3", 15000);
NetworkStream stream = client.GetStream();
int number = stream.ReadByte();
stream.Close();
client.Close();

TCP-сервер:

TcpListener server = new TcpListener(IPAddress.IPv6Any, 15000);
server.Start();

TcpClient client = server.AcceptTcpClient();
NetworkStream stream = client.GetStream();
stream.WriteByte(199);
stream.Close();
client.Close();

Версия Ubuntu: 16.04 LTS

Mono версия: 4.6 Service Release 0.1 (4.6.1.5)

В чем может быть проблема?

1 ответ

Решение

Я нашел проблему. Локальные адреса канала IPv6 связаны с числом, называемым идентификатором области действия, которое указывает сетевой интерфейс, который мы хотели бы использовать для соединения. Похоже, что в системах Linux мы должны явно предоставить эту информацию (даже с помощью ping6, мы должны это сделать), но в Windows нет таких требований, и согласно этой статье https://technet.microsoft.com/pl-pl/ms739166 он использует Neighbor Discovery и пытается найти для нас подходящий интерфейс.

Например: в Windows ping fe80::3 будет работать правильно, но в Linux нам нужно сделать ping6 -I eth0 fe80::3 или же ping6 fe80::3%2

Клиент TCP должен был быть немного изменен, чтобы соответствовать идентификатору области и указать сетевой интерфейс, который он будет использовать для правильной работы:

IPAddress ipAddress = null;

foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces())
{
    IPInterfaceProperties ipIntProperties = networkInterface.GetIPProperties();
    foreach (UnicastIPAddressInformation addr in ipIntProperties.UnicastAddresses)
    {
        String addressWithoutScopeId = addr.Address.ToString().Split('%')[0];
        if (addressWithoutScopeId.Equals("fe80::2"))
        {
            ipAddress = addr.Address;
            break;
         }

     }
     if (ipAddress != null)
         break;
}

var endPoint = new IPEndPoint(ipAddress, 0);
TcpClient client = new TcpClient(endPoint);
client.Connect(IPAddress.Parse("fe80::3"), 15000);
NetworkStream stream = client.GetStream();
int number = stream.ReadByte();
stream.Close();
client.Close();
Другие вопросы по тегам