none
Поведение TcpClient при повторном вызове метода Connect RRS feed

  • Общие обсуждения

  • Здравствуйте!

    Управляемое сетевое приложение. Есть объект client класса TcpClient. Первый вызов метода Connect(...) устанавливает соединение с удаленной точкой, все работает. Если повторно вызвать Connect(...) на этом же объекте с той же самой удаленной точкой, возбуждается исключение:

    "System.Net.Sockets.SocketException: Сделан запрос на подключение для уже подключенного сокета 127.0.0.1:8083

    Server stack trace:
       в System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
       в System.Net.Sockets.Socket.Connect(EndPoint remoteEP)
       в System.Net.Sockets.TcpClient.Connect(IPEndPoint remoteEP)
       в System.Net.Sockets.TcpClient.Connect(IPAddress address, Int32 port)
       в System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs)
       в System.Runtime.Remoting.Messaging.StackBuilderSink.AsyncProcessMessage(IMessage msg, IMessageSink replySink)"

    Поведение, на первый взгляд, понятное - вопросов нет. Однако, почему после этого (повторного, ошибочного) вызова Connect(....) свойства объектов client.Connected и client.client.Connected (сокета) "чудесным образом" становятся false??? Причем, свойство client.cient.Handle не меняется. Получается, что ошибочный вызов метода Connect(...) фиксируется, опознается, но приводит к "потере" работоспособного канала.

    Сейчас попробовал на C++ через сокеты Winsock2 - если повторно вызвать connect для уже открытого сокета, просто возвращается "Socket is already connected" (WSAEISCONN). Канал продолжает прекрасно работать.

    Подозреваю, что это такая реализация MS в недрах .net framework. По-видимому, логика следующая. Перехват исключений не всегда реализуется программистом,  и в этом случае исключение может привести к краху всего приложения. Если не закрыть сокет и не очистить ресурсы - произойдет "потеря" неуправляемого ресурса системы в виде сокета. Надежнее будет закрыть сокет и возбудить исключение. Что побудит программиста "разобраться" с проблемой.

    Выход - не позволять повторный вызов Connect, если TCP-соединение уже установлено.

    Microsoft - отобразить в документации этот побочный эффект вызова TcpClient.Connect(...), которые завершаются исключением.

    Удачи всем.

    30 ноября 2014 г. 14:51

Все ответы

  • Сколько кодил не разу не замечал этого. Наверное потому что всегда перед повторным вызовом Connect проверял значение Connected.

    В любом случае вы правы, о таком поведении стоит сообщать в документации.


    VB.Net - WPF, WinRT, WP

    1 декабря 2014 г. 7:39
    Отвечающий