Класс Socket

Последнее обновление: 06.11.2022

В основе межсетевых взаимодействий по сетевых протоколам TCP и UDP лежат сокеты. Сокет предоставляет интерфейс доступа к определенному порту определенного хоста. То есть через сокет один хост может обращаться к приложению на другом хосте. В .NET сокеты представлены классом Socket из пространства имен System.NET.Sockets, который предоставляет низкоуровневый интерфейс для приема и отправки сообщений по сети.

Определение сокета

Для создания объекта сокета можно использовать один из его конструкторов.

  • Socket(AddressFamily, SocketType, ProtocolType): создает сокет, используя указанные семейство адресов, тип сокета и протокол.

  • Socket(SafeSocketHandle): создает сокет с помощью дескриптора сокета - объекта SafeSocketHandle.

  • Socket(SocketInformation): создает сокет, используя структуру SocketInformation.

  • Socket(SocketType, ProtocolType): создает сокет, используя указанные тип сокета и протокол.

Возьмем первый вариант конструктора с тремя параметра:

  • Первый параметр конструктора представляет перечисление AddressFamily и задает схему адресации, которую может использовать сокет. Данное перечисление содержит 33 константы. Наиболее используемые:

    • InterNetwork: адрес по протоколу IPv4

    • InterNetworkV6: адрес по протоколу IPv6

    • Ipx: адрес IPX или SPX

    • NetBios: адрес NetBios

  • Второй параметр представляет перечисление SocketType, которое устанавливает тип сокета. Может принимать следующие значения:

    • Dgram: сокет будет получать и отправлять дейтаграммы по протоколу Udp. Данный тип сокета работает в связке с типом протокола - Udp и значением AddressFamily.InterNetwork

    • Raw: сокет имеет доступ к нижележащему протоколу транспортного уровня и может использовать для передачи сообщений такие протоколы, как ICMP и IGMP

    • Rdm: сокет может взаимодействовать с удаленными хостами без установки постоянного подключения. В случае, если отправленные сокетом сообщения невозможно доставить, то сокет получит об этом уведомление

    • Seqpacket: обеспечивает надежную двустороннюю передачу данных с установкой постоянного подключения

    • Stream: обеспечивает надежную двустороннюю передачу данных с установкой постоянного подключения. Для связи используется протокол TCP, поэтому этот тип сокета используется в паре с типом протокола Tcp и значением AddressFamily.InterNetwork

    • Unknown: адрес NetBios

  • Третий параметр представляет перечисление ProtocolType, которое устанавливает тип используемого протокола. Может принимать следующие значения:

    • Ggp

    • Icmp

    • IcmpV6

    • Idp

    • Igmp

    • IP

    • IPSecAuthenticationHeader (Заголовок IPv6 AH)

    • IPSecEncapsulatingSecurityPayload (Заголовок IPv6 ESP)

    • IPv4

    • IPv6

    • IPv6DestinationOptions (Заголовок IPv6 Destination Options)

    • IPv6FragmentHeader (Заголовок IPv6 Fragment)

    • IPv6HopByHopOptions (Заголовок IPv6 Hop by Hop Options)

    • IPv6NoNextHeader (Заголовок IPv6 No next)

    • IPv6RoutingHeader (Заголовок IPv6 Routing)

    • Ipx

    • ND

    • Pup

    • Raw

    • Spx

    • SpxII

    • Tcp

    • Udp

    • Unknown (неизвестный протокол)

    • Unspecified (неуказанный протокол)

    Каждое значение представляет соответствующий протокол, но наиболее используемыми являются Tcp и Udp.

Например, определим сокет, который использует протокол Tcp:

using System.Net.Sockets;
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

Или сокет, использующий протокол Udp:

using System.Net.Sockets;
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

Таким образом, при создании сокета мы можем указывать разные комбинации протоколов, типов сокета, значений из перечисления AddressFamily. Однако в то же время не все комбинации являются корректными. Так, для работы через протокол Tcp применяется следующий набор параметров: AddressFamily.InterNetwork, SocketType.Stream и ProtocolType.Tcp. Для Udp набор параметров будет другим: AddressFamily.InterNetwork, SocketType.Dgram и ProtocolType.Udp. Для других протоколов набор значений будет отличаться. Поэтому использование сокетов может потребовать некоторого знания принципов работы отдельных протоколов. Хотя в отношении Tcp и Udp все относительно просто.

Свойства и методы сокета

свойства класса позволяют получить информацию о сокете. Основные свойства:

  • AddressFamily: представляет схему адресации, используемую сокетом, в виде перечисления AddressFamily

  • Available: возвращает объем данных, полученных от подключенного хоста и доступных для чтения

  • Connected: возвращает true, если сокет подключен к удаленному хосту

  • LocalEndPoint: возвращает локальную точку (объект типа EndPoint), по которой запущен сокет и по которой он принимает данные

  • ProtocolType: возвращает тип протокола в виде значения перечисления ProtocolType

  • RemoteEndPoint: возвращает адрес удаленного хоста, к которому подключен сокет (объект типа EndPoint)

  • SocketType: возвращает тип сокета в виде значения перечисления SocketType

При работе с сокетами вне зависимости от выбранных протоколов мы будем опираться на методы класса Socket:

  • Accept() / AcceptAsync(): создает новый объект Socket для обработки входящего подключения

  • Bind(): связывает объект Socket с локальной конечной точкой

  • Close(): закрывает сокет

  • Connect() / ConnectAsync: устанавливает соединение с удаленным хостом

  • Listen(): начинает прослушивание входящих запросов

  • Poll(): определяет состояние сокета

  • Receive() / ReceiveAsync: получает данные

  • ReceiveFrom() / ReceiveFromAsync(): получает данные и сохраняет конечную точку, от которой получены данные

  • Send() / SendAsync(): отправляет данные

  • SendTo() / SendToAsync(): отправляет данные на определенную конечную точку

  • Shutdown(): блокирует на сокете прием и/или отправку данных

В зависимости от применяемого протокола (TCP, UDP и т.д.) общий принцип работы с сокетами будет немного различаться.

При применении протокола, который требует установление соединения, например, TCP, сервер должен вызвать метод Bind для установки точки для прослушивания входящих подключений и затем запустить прослушивание подключений с помощью метода Listen. Далее с помощью метода Accept можно получить входящие запросы на подключение в виде объекта Socket, который используется для взаимодействия с удаленным узла. У полученного объекта Socket вызываются методы Send и Receive соответственно для отправки и получения данных. Если необходимо подключиться к серверу, то вызывается метод Connect. Для обмена данными с сервером также применяются методы Send или Receive.

Если применяется протокол, для которого не требуется установление соединения, например, UDP, то после вызова метода Bind не надо вызывать метод Listen. И в этом случае для приема данных используется метод ReceiveFrom() / ReceiveFromAsync(), а для отправки данных - метод SendTo() / SendToAsync().

Закрытие сокета

После завершения работы с сокетом рекомендуется его закрыть. Для этого можно использовать метод Close(). Он закрывает подключение с удаленным хостом и освобождает все управляемые и неуправляемые ресурсы, связанные с сокетом. После этого свойство Connected будет равно false

Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// работа с сокетом socket
// ...............
socket.Close();

Также можно применять конструкцию using:

using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
    // работа с сокетом socket
    // ...............
}

При работе с протоколами, ориентированными на установку соединения, например, TCP, Microsoft рекомендует перед методом Close вызывать метод Shutdown, который блокирует примем и отправку данных для сокета и гарантирует, что все данные будут получены и отправлены перед закрытием сокета.

Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

try
{
    socket.Shutdown(SocketShutdown.Both);
}
catch(Exception ex)
{
    Console.WriteLine(ex.Message);
}
finally
{
    socket.Close();
}

В качестве параметра в метод Shutdown передается значение из перечисления SocketShutdown:

  • Send: блокируется отправка данных

  • Receive: блокируется получение данных

  • Both: блокируются отправка и получение данных

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850