Использование сокетов для отправки и получения данных через TCP
Перед использованием сокета для связи с удаленными устройствами необходимо инициализировать сокет, указав протокол и сведения о сетевом адресе. Конструктор класса Socket имеет параметры, которые определяют семейство адресов, тип сокета и тип протокола, которые сокет использует для подключения. При подключении сокета клиента к сокету сервера клиент будет использовать IPEndPoint
объект для указания сетевого адреса сервера.
Создание конечной точки IP
При работе System.Net.Socketsс объектом представляется сетевая конечная точка IPEndPoint . Создается IPEndPoint
с соответствующим номером IPAddress порта. Прежде чем начать беседу с помощью Socket, создайте канал данных между приложением и удаленным назначением.
В качестве уникального идентификатора службы протокол TCP/IP использует сетевой адрес и номер порта службы. Сетевой адрес определяет определенное назначение сети; Номер порта определяет определенную службу на этом устройстве для подключения. Сочетание сетевого адреса и порта службы называется конечной точкой, которая представлена в .NET классом EndPoint . Потомок EndPoint
определяется для каждого поддерживаемого семейства адресов; для семейства IP-адресов класс имеет значение IPEndPoint.
Класс Dns предоставляет службы доменных имен приложениям, используюющим интернет-службы TCP/IP. Метод GetHostEntryAsync запрашивает DNS-сервер для сопоставления понятного доменного имени (например, "host.contoso.com") с числовым интернет-адресом (например 192.168.1.1
, ). GetHostEntryAsync
возвращает значение Task<IPHostEntry>
, которое, когда ожидается, содержит список адресов и псевдонимов для запрошенного имени. В большинстве случаев можно использовать первый адрес из возвращенного массива AddressList. Следующий код получает IPAddress IP-адрес сервера host.contoso.com
.
IPHostEntry ipHostInfo = await Dns.GetHostEntryAsync("host.contoso.com");
IPAddress ipAddress = ipHostInfo.AddressList[0];
Совет
Для ручного тестирования и отладки метод обычно можно использовать GetHostEntryAsync с результирующий имя узла из Dns.GetHostName() значения для разрешения имени localhost на IP-адрес. Рассмотрим следующий фрагмент кода:
var hostName = Dns.GetHostName();
IPHostEntry localhost = await Dns.GetHostEntryAsync(hostName);
// This is the IP address of the local machine
IPAddress localIpAddress = localhost.AddressList[0];
Центр назначения номеров Интернета (IANA) определяет номера портов для общих служб. Дополнительные сведения см. в разделе IANA: Имя службы и реестр номеров портов транспорта). Другие службы могут использовать номера портов в диапазоне от 1024 до 65535. Следующий код объединяет IP-адрес host.contoso.com
с номером порта, чтобы создать удаленную конечную точку для подключения.
IPEndPoint ipEndPoint = new(ipAddress, 11_000);
После определения адреса удаленного устройства и выбора порта, используемого для подключения, приложение может установить подключение к удаленному устройству.
Socket
Создание клиента
endPoint
Создав объект, создайте сокет клиента для подключения к серверу. После подключения сокета он может отправлять и получать данные из подключения сокета сервера.
using Socket client = new(
ipEndPoint.AddressFamily,
SocketType.Stream,
ProtocolType.Tcp);
await client.ConnectAsync(ipEndPoint);
while (true)
{
// Send message.
var message = "Hi friends 👋!<|EOM|>";
var messageBytes = Encoding.UTF8.GetBytes(message);
_ = await client.SendAsync(messageBytes, SocketFlags.None);
Console.WriteLine($"Socket client sent message: \"{message}\"");
// Receive ack.
var buffer = new byte[1_024];
var received = await client.ReceiveAsync(buffer, SocketFlags.None);
var response = Encoding.UTF8.GetString(buffer, 0, received);
if (response == "<|ACK|>")
{
Console.WriteLine(
$"Socket client received acknowledgment: \"{response}\"");
break;
}
// Sample output:
// Socket client sent message: "Hi friends 👋!<|EOM|>"
// Socket client received acknowledgment: "<|ACK|>"
}
client.Shutdown(SocketShutdown.Both);
В приведенном выше коде C#:
Создает экземпляр нового
Socket
объекта с заданнымendPoint
семейством адресов экземпляров, SocketType.Streamа также ProtocolType.Tcp.Socket.ConnectAsync Вызывает метод с
endPoint
экземпляром в качестве аргумента.В цикле
while
:- Кодирует и отправляет сообщение серверу с помощью Socket.SendAsync.
- Записывает отправленное сообщение в консоль.
- Инициализирует буфер для получения данных с сервера с помощью Socket.ReceiveAsync.
response
Когда подтверждение является подтверждением, он записывается в консоль и цикл завершается.
Наконец, вызовы Socket.Shutdown сокета, заданные
client
SocketShutdown.Both, что завершает работу как операций отправки, так и получения.
Socket
Создание сервера
Чтобы создать сокет сервера, endPoint
объект может прослушивать входящие подключения по любому IP-адресу, но необходимо указать номер порта. После создания сокета сервер может принимать входящие подключения и взаимодействовать с клиентами.
using Socket listener = new(
ipEndPoint.AddressFamily,
SocketType.Stream,
ProtocolType.Tcp);
listener.Bind(ipEndPoint);
listener.Listen(100);
var handler = await listener.AcceptAsync();
while (true)
{
// Receive message.
var buffer = new byte[1_024];
var received = await handler.ReceiveAsync(buffer, SocketFlags.None);
var response = Encoding.UTF8.GetString(buffer, 0, received);
var eom = "<|EOM|>";
if (response.IndexOf(eom) > -1 /* is end of message */)
{
Console.WriteLine(
$"Socket server received message: \"{response.Replace(eom, "")}\"");
var ackMessage = "<|ACK|>";
var echoBytes = Encoding.UTF8.GetBytes(ackMessage);
await handler.SendAsync(echoBytes, 0);
Console.WriteLine(
$"Socket server sent acknowledgment: \"{ackMessage}\"");
break;
}
// Sample output:
// Socket server received message: "Hi friends 👋!"
// Socket server sent acknowledgment: "<|ACK|>"
}
В приведенном выше коде C#:
Создает экземпляр нового
Socket
объекта с заданнымendPoint
семейством адресов экземпляров, SocketType.Streamа также ProtocolType.Tcp.Socket.Bind Вызывает
listener
метод сendPoint
экземпляром в качестве аргумента для связывания сокета с сетевым адресом.Метод Socket.Listen() вызывается для прослушивания входящих подключений.
Вызывает
listener
метод для принятия входящего подключения в сокетеhandler
.Socket.AcceptAsyncВ цикле
while
:- Вызовы Socket.ReceiveAsync для получения данных от клиента.
- После получения данных он декодируется и записывается в консоль.
response
Если сообщение заканчивается<|EOM|>
, подтверждение отправляется клиенту с помощью Socket.SendAsync.
Запуск примера клиента и сервера
Сначала запустите серверное приложение и запустите клиентское приложение.
dotnet run --project socket-server
Socket server starting...
Found: 172.23.64.1 available on port 9000.
Socket server received message: "Hi friends 👋!"
Socket server sent acknowledgment: "<|ACK|>"
Press ENTER to continue...
Клиентское приложение отправит на сервер сообщение, и сервер будет отвечать на подтверждение.
dotnet run --project socket-client
Socket client starting...
Found: 172.23.64.1 available on port 9000.
Socket client sent message: "Hi friends 👋!<|EOM|>"
Socket client received acknowledgment: "<|ACK|>"
Press ENTER to continue...