Соединение TcpClient завершается неудачно с IPv6Any - PullRequest
5 голосов
/ 17 ноября 2011

Проблема в том, что следующий код работает хорошо, если IPAddress.Any был задан в качестве параметра, но выдает ошибку, если используется `IPAddress.IPv6Any.

Я получаю сообщение об ошибке # 10057

Сокет не подключен.

Запрос на отправку или получение данных был отклонен, поскольку сокет не подключен и (при отправкена сокете датаграмм с использованием sendto) адрес не был указан.Любой другой тип операции может также вернуть эту ошибку - например, настройка setsockopt SO_KEEPALIVE, если соединение было сброшено.

Почему он не работает как IPv6Any?Я почти уверен, что это не брандмауэр, так как порт остается тем же, и он работает с IPv4 (и мой брандмауэр должен пропускать любые запросы, сделанные моим приложением).

Чтобы сократить код, это что-то вродеэто:

Слушатель:

listener = new TcpListener(IPAddress.IPv6Any, portNr);
listener.AllowNatTraversal(true);
listener.Start();
listener.BeginAcceptTcpClient(this.AcceptClient, null);

Клиент:

client = new TcpClient();
client.NoDelay = true;            

try
{
    this.client.Connect(ip, port);  //ip = "localhost" when connecting as server
}
catch (Exception ex)
{
    FileLogger.LogMessage(ex);
    Disconnect();
}

Я пытаюсь настроить «серверную» часть TCP-соединения.

Что я делаю, так это то, что я запускаю прослушиватель на локальном хосте, а затем подключаюсь к нему в качестве клиента (и разрешаю другим присоединяться в качестве клиентов).

То, что я пытаюсьдобиться этого можно с помощью прямой адресации этого TCP-сервера, следуя этой статье: http://blogs.msdn.com/b/ncl/archive/2009/07/27/end-to-end-connectivity-with-nat-traversal-.aspx

Причина, по которой я это делаю, заключается в том, что я хочу, чтобы человек A мог подключаться к человеку Bкогда они оба находятся за маршрутизаторами NAT.

Ответы [ 4 ]

1 голос
/ 10 апреля 2018

Я знаю, что этот ответ приходит немного поздно, но у меня тоже была эта проблема, и она была связана с клиентом. Проблема в том, что вы предоставили код ...

client = new TcpClient();

... создает экземпляр IPv4 TcpClient, который не способен интерпретировать адреса IPv6. Поэтому, если у вас уже есть IP-адрес на момент инициализации, попробуйте инициализировать ваш TcpClient следующим образом:

TcpClient client = new TcpClient(ip.AddressFamily);

Если переменная ip является строкой, вам необходимо сначала преобразовать ее в тип IP-адрес:

IPAddress iAddr = IPAddress.Parse(ip);

На самом деле IPv6-TcpClient, кажется, также совместим с IPv4-адресами, поэтому вы также можете инициализировать клиента следующим образом:

TcpClient client = new TcpClient(AddressFamily.InterNetworkV6)

Хотя верхние предложения кажутся самыми чистыми, нижние предложения кажутся более универсальными. В конце концов, это зависит от ваших предпочтений.

1 голос
/ 18 мая 2016

Я решил аналогичную проблему, когда следующая строка блокировала только соединения, приходящие с адресов IPv4:

listener = new TcpListener(IPAddress.IPv6Any, portNr);

Похоже, что сокет, настроенный на прием соединений IPv6, по умолчанию принимает ТОЛЬКО соединения IPv6. Чтобы решить эту проблему, мне пришлось обновить мой код до этого:

listener.Server.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, false);
listener.Start();
0 голосов
/ 08 апреля 2012

Когда вы используете TcpClient.Connect(string, int), вы можете прерваться из-за разрешения DNS.

Хотя Microsoft документирует, что IPv6-адрес будет пробоваться первым, разрешение может возвращать только адреса IPv4.

http://msdn.microsoft.com/en-us/library/8s2yca91.aspx

Таким образом, вы можете попробовать TcpClient.Connect(IPAddress.IPv6Loopback, port) на стороне клиента, чтобы проверить, работает ли он?

0 голосов
/ 08 апреля 2012
IPAddress.Loopback == FAIL
IPAddress.IPv6Loopback == SUCCESS

Возможно, localhost сопоставляется с IPv4 Loopback адресом в вашем случае?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...