Работа с сокетами на c


Содержание

Работа с WinSocket в Visual C++ / Сокеты / Сеть

Работа с WinSocket в Visual C++

Socket (гнездо, разъем) — абстрактное программное понятие, используемое для обозначения в прикладной программе конечной точки канала связи с коммуникационной средой, образованной вычислительной сетью. При использовании протоколов TCP/IP можно говорить, что socket является средством подключения прикладной программы к порту (см. выше) локального узла сети.

Socket-интерфейс представляет собой просто набор системных вызовов и/или библиотечных функций языка программирования СИ, разделенных на четыре группы:

Ниже рассматривается подмножество функций socket-интерфейса, достаточное для написания сетевых приложений, реализующих модель «клиент-сервер» в режиме с установлением соединения.

1. Функции локального управления

Функции локального управления используются, главным образом, для выполнения подготовительных действий, необходимых для организации взаимодействия двух программ-партнеров. Функции носят такое название, поскольку их выполнение носит локальный для программы характер.

1.1 Создание socket’а

Создание socket’а осуществляется следующим системным вызовом #include int socket (domain, type, protocol) int domain; int type; int protocol;

Аргумент domain задает используемый для взаимодействия набор протоколов (вид коммуникационной области), для стека протоколов TCP/IP он должен иметь символьное значение AF_INET (определено в sys/socket.h).

Аргумент type задает режим взаимодействия:

  • SOCK_STREAM — с установлением соединения;
  • SOCK_DGRAM — без установления соединения.

Аргумент protocolзадает конкретный протокол транспортного уровня (из нескольких возможных в стеке протоколов). Если этот аргумент задан равным 0, то будет использован протокол «по умолчанию» (TCP для SOCK_STREAM и UDP для SOCK_DGRAM при использовании комплекта протоколов TCP/IP).

При удачном завершении своей работы данная функция возвращает дескриптор socket’а — целое неотрицательное число, однозначно его идентифицирующее. Дескриптор socket’а аналогичен дескриптору файла ОС UNIX.

При обнаружении ошибки в ходе своей работы функция возвращает число «-1».

1.2. Связывание socket’а

Для подключения socket’а к коммуникационной среде, образованной вычислительной сетью, необходимо выполнить системный вызов bind, определяющий в принятом для сети формате локальный адрес канала связи со средой. В сетях TCP/IP socket связывается с локальным портом. Системный вызов bind имеет следующий синтаксис:

Аргумент s задает дескриптор связываемого socket’а.

Аргумент addr в общем случае должен указывать на структуру данных, содержащую локальный адрес, приписываемый socket’у. Для сетей TCP/IP такой структурой является sockaddr_in.

Аргумент addrlen задает размер (в байтах) структуры данных, указываемой аргументом addr.

Структура sockaddr_in используется несколькими системными вызовами и функциями socket-интерфейса и определена в include-файле in.h следующим образом:

Поле sin_family определяет используемый формат адреса (набор протоколов), в нашем случае (для TCP/IP) оно должно иметь значение AF_INET.

Поле sin_addr содержит адрес (номер) узла сети.

Поле sin_port содержит номер порта на узле сети.

Поле sin_zero не используется.

Определение структуры in_addr (из того же include-файла) таково:

Структура sockaddr_in должна быть полностью заполнена перед выдачей системного вызова bind. При этом, если поле sin_addr.s_addr имеет значение INADDR_ANY, то системный вызов будет привязывать к socket’у номер (адрес) локального узла сети.

В случае успеха bind возвращает 0, в противном случае — «-1».

2. Функции установления связи

Для установления связи «клиент-сервер» используются системные вызовы listen и accept (на стороне сервера), а также connect (на стороне клиента). Для заполнения полей структуры socaddr_in, используемой в вызове connect, обычно используется библиотечная функция gethostbyname, транслирующая символическое имя узла сети в его номер (адрес).

2.1. Ожидание установления связи

Системный вызов listen выражает желание выдавшей его программы-сервера ожидать запросы к ней от программ-клиентов и имеет следующий вид:

Аргумент s задает дескриптор socket’а, через который программа будет ожидать запросы к ней от клиентов. Socket должен быть предварительно создан системным вызовом socketи обеспечен адресом с помощью системного вызова bind.

Аргумент n определяет максимальную длину очереди входящих запросов на установление связи. Если какой-либо клиент выдаст запрос на установление связи при полной очереди, то этот запрос будет отвергнут.

Признаком удачного завершения системного вызова listen служит нулевой код возврата.

2.2. Запрос на установление соединения

Для обращения программы-клиента к серверу с запросом на установление логической соединения используется системный вызов connect, имеющий следующий вид #include #include #include int connect (s, addr, addrlen) int s; struct sockaddr_in *addr; int addrlen;

Аргумент s задает дескриптор socket’а, через который программа обращается к серверу с запросом на соединение. Socket должен быть предварительно создан системным вызовом socketи обеспечен адресом с помощью системного вызова bind.

Аргумент addr должен указывать на структуру данных, содержащую адрес, приписанный socket’у программы-сервера, к которой делается запрос на соединение. Для сетей TCP/IP такой структурой является sockaddr_in. Для формирования значений полей структуры sockaddr_in удобно использовать функцию gethostbyname.

Аргумент addrlen задает размер (в байтах) структуры данных, указываемой аргументом addr.

Для того, чтобы запрос на соединение был успешным, необходимо, по крайней мере, чтобы программа-сервер выполнила к этому моменту системный вызов listen для socket’а с указанным адресом.

При успешном выполнении запроса системный вызов connect возвращает 0, в противном случае — «-1» (устанавливая код причины неуспеха в глобальной переменной errno).

Примечание. Если к моменту выполнения connect используемый им socket не был привязан к адресу посредством bind ,то такая привязка будет выполнена автоматически.

Примечание. В режиме взаимодействия без установления соединения необходимости в выполнении системного вызова connect нет. Однако, его выполнение в таком режиме не является ошибкой — просто меняется смысл выполняемых при этом действий: устанавливается адрес «по умолчанию» для всех последующих посылок дейтаграмм.

2.3. Прием запроса на установление связи

Для приема запросов от программ-клиентов на установление связи в программах-серверах используется системный вызов accept, имеющий следующий вид:

Аргумент s задает дескриптор socket’а, через который программа-сервер получила запрос на соединение (посредством системного запроса listen ).

Аргумент addr должен указывать на область памяти, размер которой позволял бы разместить в ней структуру данных, содержащую адрес socket’а программы-клиента, сделавшей запрос на соединение. Никакой инициализации этой области не требуется.

Аргумент p_addrlen должен указывать на область памяти в виде целого числа, задающего размер (в байтах) области памяти, указываемой аргументом addr.

Системный вызов accept извлекает из очереди, организованной системным вызовом listen, первый запрос на соединение и возвращает дескриптор нового (автоматически созданного) socket’а с теми же свойствами, что и socket, задаваемый аргументом s. Этот новый дескриптор необходимо использовать во всех последующих операциях обмена данными.

Кроме того после удачного завершения accept:

  • область памяти, указываемая аргументом addr, будет содержать структуру данных (для сетей TCP/IP это sockaddr_in), описывающую адрес socket’а программы-клиента, через который она сделала свой запрос на соединение;
  • целое число, на которое указывает аргумент p_addrlen, будет равно размеру этой структуры данных.

Если очередь запросов на момент выполнения accept пуста, то программа переходит в состояние ожидания поступления запросов от клиентов на неопределенное время (хотя такое поведение accept можно и изменить).

Признаком неудачного завершения accept служит отрицательное возвращенное значение (дескриптор socket’а отрицательным быть не может).

Примечание. Системный вызов accept используется в программах-серверах, функционирующих только в режиме с установлением соединения.

2.4. Формирование адреса узла сети

Для получения адреса узла сети TCP/IP по его символическому имени используется библиотечная функция

Аргумент name задает адрес последовательности литер, образующих символическое имя узла сети.

При успешном завершении функция возвращает указатель на структуру hostent, определенную в include-файле netdb.h и имеющую следующий вид struct hostent < char *h_name; char **h_aliases; int h_addrtype; int h_lenght; char *h_addr; >;

Поле h_name указывает на официальное (основное) имя узла.

Поле h_aliases указывает на список дополнительных имен узла (синонимов), если они есть.

Поле h_addrtype содержит идентификатор используемого набора протоколов, для сетей TCP/IP это поле будет иметь значение AF_INET.

Поле h_lenght содержит длину адреса узла.

Поле h_addr указывает на область памяти, содержащую адрес узла в том виде, в котором его используют системные вызовы и функции socket-интерфейса.

Пример обращения к функции gethostbyname для получения адреса удаленного узла в программе-клиенте, использующей системный вызов connect для формирования запроса на установления соединения с программой-сервером на этом узле, рассматривается ниже.

3. Функции обмена данными

В режиме с установлением логического соединения после удачного выполнения пары взаимосвязанных системных вызовов connect (в клиенте) и accept (в сервере) становится возможным обмен данными.

Этот обмен может быть реализован обычными системными вызовами read и write, используемыми для работы с файлами (при этом вместо дескрипторов файлов в них задаются дескрипторы socket’ов).

Кроме того могут быть дополнительно использованы системные вызовы send и recv, ориентированные специально на работу с socket’ами.

Примечание. Для обмена данными в режиме без установления логического соединения используются, как правило, системные вызовы sendtoи recvfrom. Sendto позволяет специфицировать вместе с передаваемыми данными (составляющими дейтаграмму) адрес их получателя. Recvfrom одновременно с доставкой данных получателю информирует его и об адресе отправителя.

3.1. Посылка данных

Для посылки данных партнеру по сетевому взаимодействию используется системный вызов send, имеющий следующий вид

Аргумент s задает дескриптор socket’а, через который посылаются данные.

Аргумент buf указывает на область памяти, содержащую передаваемые данные.

Аргумент len задает длину (в байтах) передаваемых данных.

Аргумент flags модифицирует исполнение системного вызова send. При нулевом значении этого аргумента вызов send полностью аналогичен системному вызову write.

При успешном завершении send возвращает количество переданных из области, указанной аргументом buf, байт данных. Если канал данных, определяемый дескриптором s, оказывается «переполненным», то send переводит программу в состояние ожидания до момента его освобождения.

3.2. Получение данных

Для получения данных от партнера по сетевому взаимодействию используется системный вызов recv, имеющий следующий вид

Аргумент s задает дескриптор socket’а, через который принимаются данные.

Аргумент buf указывает на область памяти, предназначенную для размещения принимаемых данных.

Аргумент len задает длину (в байтах) этой области.

Аргумент flags модифицирует исполнение системного вызова recv. При нулевом значении этого аргумента вызов recv полностью аналогичен системному вызову read.

При успешном завершении recv возвращает количество принятых в область, указанную аргументом buf, байт данных. Если канал данных, определяемый дескриптором s, оказывается «пустым», то recv переводит программу в состояние ожидания до момента появления в нем данных.

4. Функции закрытия связи

Для закрытия связи с партнером по сетевому взаимодействию используются системные вызовы close и shutdown.

4.1. Системный вызов close

Для закрытия ранее созданного socket’а используется обычный системный вызов close, применяемый в ОС UNIX для закрытия ранее открытых файлов и имеющий следующий вид

Аргумент s задает дескриптор ранее созданного socket’а.

Однако в режиме с установлением логического соединения (обеспечивающем, как правило, надежную доставку данных) внутрисистемные механизмы обмена будут пытаться передать/принять данные, оставшиеся в канале передачи на момент закрытия socket’а. На это может потребоваться значительный интервал времени, неприемлемый для некоторых приложений. В такой ситуации необходимо использовать описываемый далее системный вызов shutdown.

4.2. Сброс буферизованных данных

Для «экстренного» закрытия связи с партнером (путем «сброса» еще не переданных данных) используется системный вызов shutdown, выполняемый перед close и имеющий следующий вид

Аргумент s задает дескриптор ранее созданного socket’а.

Аргумент how задает действия, выполняемые при очистке системных буферов socket’а:

0 — сбросить и далее не принимать данные для чтения из socket’а;

1 — сбросить и далее не отправлять данные для посылки через socket;

2 — сбросить все данные, передаваемые через socket в любом направлении.

5. Пример использования socket-интерфейса

В данном разделе рассматривается использование socket-интерфейса в режиме взаимодействия с установлением логического соединения на очень простом примере взаимодействия двух программ (сервера и клиента), функционирующих на разных узлах сети TCP/IP.

Содержательная часть программ примитивна:

сервер, приняв запрос на соединение, передает клиенту вопрос «Who are you?»;

клиент, получив вопрос, выводит его в стандартный вывод и направляет серверу ответ «I am your client» и завершает на этом свою работу;

сервер выводит в стандартный вывод ответ клиента, закрывает с ним связь и переходит в состояние ожидания следующего запроса к нему.

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

5.1. Программа-сервер

Текст программы-сервера на языке программирования СИ выглядит следующим образом

Строки 1. 5 описывают включаемые файлы, содержащие определения для всех необходимых структур данных и символических констант.

Строка 6 приписывает целочисленной константе 1234 символическое имя SRV_PORT. В дальнейшем эта константа будет использована в качестве номера порта сервера. Значение этой константы должно быть известно и программе-клиенту.

Строка 7 приписывает целочисленной константе 64 символическое имя BUF_SIZE. Эта константа будет определять размер буфера, используемого для размещения принимаемых от клиента данных.

Строка 8 приписывает последовательности символов, составляющих текст вопроса клиенту, символическое имя TXT_QUEST. Последним символом в последовательности является символ перехода на новую строку ‘\n’. Сделано это для упрощения вывода текста вопроса на стороне клиента.

В строке 14 создается (открывается) socket для организации режима взаимодействия с установлением логического соединения (SOCK_STREAM) в сети TCP/IP (AF_INET), при выборе протокола транспортного уровня используется протокол «по умолчанию» (0).

В строках 15. 18 сначала обнуляется структура данных sin, а затем заполняются ее отдельные поля. Использование константы INADDR_ANY упрощает текст программы, избавляя от необходимости использовать функцию gethostbyname для получения адреса локального узла, на котором запускается сервер.

Строка 19 посредством системного вызова bind привязывает socket, задаваемый дескриптором s, к порту с номером SRV_PORT на локальном узле. Bind завершится успешно при условии, что в момент его выполнения на том же узле уже не функционирует программа, использующая этот номер порта.

Строка 20 посредством системного вызова listen организует очередь на три входящих к серверу запроса на соединение.

Строка 21 служит заголовком бесконечного цикла обслуживания запросов от клиентов.

На строке 23, содержащей системный вызов accept, выполнение программы приостанавливается на неопределенное время, если очередь запросов к серверу на установление связи оказывается пуста. При появлении такого запроса accept успешно завершается, возвращая в переменной s_new дескриптор socket’а для обмена информацией с клиентом.

В строке 24 сервер с помощью системного вызова write отправляет клиенту вопрос.

В строке 25 с помощью системного вызова read читается ответ клиента.

В строке 26 ответ направляется в стандартный вывод, имеющий дескриптор файла номер 1. Так как строка ответа содержит в себе символ перехода на новую строку, то текст ответа будет размещен на отдельной строке дисплея.

Строка 27 содержит системный вывод shutdown, обеспечивающий очистку системных буферов socket’а, содержащих данные для чтения («лишние» данные могут там оказаться в результате неверной работы клиента).

В строке 28 закрывается (удаляется) socket, использованный для обмена данными с очередным клиентом.

Примечание. Данная программа (как и большинство реальных программ-серверов) самостоятельно своей работы не завершает, находясь в бесконечном цикле обработки запросов клиентов. Ее выполнение может быть прервано только извне путем посылки ей сигналов (прерываний) завершения. Правильно разработанная программа-сервер должна обрабатывать такие сигналы, корректно завершая работу (закрывая, в частности, посредством close socket с дескриптором s).

5.2. Программа-клиент

Текст программы-клиента на языке программирования СИ выглядит следующим образом

В строках 6 и 7 описываются константы SRV_HOST и SRV_PORT, определяющие имя удаленного узла, на котором функционирует программа-сервер, и номер порта, к которому привязан socket сервера.

Строка 8 приписывает целочисленной константе 1235 символическое имя CLNT_PORT. В дальнейшем эта константа будет использована в качестве номера порта клиента.

В строках 17. 22 создается привязанный к порту на локальном узле socket.

В строке 24 посредством библиотечной функции gethostbyname транслируется символическое имя удаленного узла (в данном случае «delta»), на котором должен функционировать сервер, в адрес этого узла, размещенный в структуре типа hostent.

В строке 26 адрес удаленного узла копируется из структуры типа hostent в соответствующее поле структуры srv_sin, которая позже (в строке 28) используется в системном вызове connect для идентификации программы-сервера.

В строках 29. 31 осуществляется обмен данными с сервером и вывод вопроса, поступившего от сервера, в стандартный вывод.

Строка 32 посредством системного вызова close закрывает (удаляет) socket.

Программирование сетевых приложений (TCP/IP) на C/C++

Простейшие примеры

TCP/IP

Что следует иметь ввиду при разработке с TCP

  1. TCP не выполняет опрос соединения (не поможет даже keep alive — он нужен для уборки мусора, а не контроля за состоянием соединения). Исправляется на прикладном уровне, например, реализацией пульсации. Причем на дополнительном соединении.
  2. Задержки при падении хостов, разрыве связи.
  3. Необходимо следить за порядком получения сообщений.
  4. Заранее неизвестно сколько данных будет прочитано из сокета. Может быть прочитано несколько пакетов сразу!
  5. Надо быть готовым ко всем внештатным ситуациям:
    • постоянный или временный сбой сети
    • отказ принимающего приложения
    • аварийный сбой самого хоста на принимающей стороне
    • неверное поведение хоста на принимающей стороне
    • учитывать особенности сети функционирования приложения (глобальная или локальная)

OSI и TCP/IP

OSI TCP/IP
Прикладной уровень Прикладной уровень
Уровень представления
Сеансовый уровень Транспортный уровень
Транспортный уровень Межсетевой уровень
Сетевой уровень Интерфейсный уровень
Канальный уровень
Физический уровень

Порты

Порт Кем контроллируется
0 — 1023 Контролируется IANA
1024 — 49151 Регистрируется в IANA
49152 — 65535 Эфимерные

Полный список зарегистрированных портов расположен по адресу: http://www.isi.edu/in-notes/iana/assignment/port-numbers. Подать заявку на получение хорошо известного или зарегистрированного номера порта можно по адресу http://www.isi.edu/cgi-bin/iana/port-numbers.pl.

Состояние TIME-WAIT

После активного закрытия для данного конкретного соединения стек входит в состояние TIME-WAIT на время 2MSL (максимальное время жизни пакета) для того, чтобы

  1. заблудившийся пакет не попал в новое соединение с такими же параметрами.
  2. если потерялся ACK, подтверждающий закрытие соединения, с активной стороны, пассивная снова пощлёт FIN, активная, игнорируя TIME-WAIT уже закрыла соединение, поэтому пассивная сторона получит RST.

Отключение состояния TIME-WAIT крайне не рекомендуется, так как это нарушает безопасность TCP соединения, тем не менее существует возможность сделать это — опция сокета SO_LINGER.

Штатная ситуация — перезагрузка сервера может пострадать из-за наличия TIME-WAIT. Эта проблема решается заданием опции SO_REUSEADDR.

Отложенное подтверждение и алгоритм Нейгла.

Алгоритм Нейгла используется для предотвращения забивания сети мелкими пакетами и имеет очень простую формулировку — запрещено посылать второй маленький пакет до тех пор, пока не придет подтверждение на первый. Тем не менее данные отправляются при выполнении хотя бы одного из следующих условий:

  • можно послать полный сегмент размером MSS (максимальный размер сегмента)
  • соединение простаивает, и можно опустошить буфер передачи
  • алгоритм Нейгла отключен, и можно опустошить буфер передачи
  • есть срочные данные для отправки
  • есть маленьки сегмент, но его отправка уже задержана на достаточно длительное время (таймер терпения persist timer на тайм-аут ретрансмиссии RTO )
  • окно приема, объявленное хостом на другом конце, открыто не менее чем на половину
  • необходимо повторно передать сегмент
  • требуется послать ACK на принятые данные
  • нужно объявить об обновлении окна

Кроме того, существует отложенное подтверждение. При этом хост, получивший сегмент, старается задержать отправку ACK, чтобы послать её вместе с данными.

Алгоритм Нейгла в купе с отложенным подтверждением в резонансе дают нежелательные задержки. Поэтому часто его отключают. Отключение алгоритма Нейгла производится заданием опции TCP_NODELAY

Но более правильным было бы проектировать приложение таким образом, чтобы было как можно меньше маленьких блоков. Лучше писать большие. Для этого можно объединять данные самостоятельно, а можно пользоваться аналогом write, работающим с несколькими буферами:

Основа сервера для игры на C# с использование сокетов для работы с протоколом UDP.

Приветствую уважаемые подписчики! Как я вам и обещал, вот он переписанный сервер чата под игру. Все основные моменты в коде хорошо прокомментировал, если вдруг у вас возникнут вопросы, пишите в комментарии или пишите мне по указанным контактам внизу поста.

Сервер состоит из четырех классов: «Program.cs», «ServerObject.cs», «ClientObject» и «User.cs»

P.S. Shift + колесико мыши — листать код влево/вправо.


Этот класс, запускает первый функционал сервера в отдельном потоке. Для того, что бы создать отдельный поток, необходимо подключить библиотеку «using System.Threading.Task;»

static void Main()

Console.Title = «Realm Server | ver. 0.1 beta alpha»;

Console.WriteLine(«Realm Server started. «);

ServerObject server = new ServerObject();

Task serverTask = new Task(server.StartServer);

Console.WriteLine(«Realm Server stoped!»);

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

private int acceptPort; // Порт для «приема» новых клиентов

public int receivePort; // Порт для приема сообщений от «подключенных клиентов»

private Socket listeningSocket; // Сокет для «приема» новых клиентов

private List users = new List (); // Список всех «подключенных» клиентов

public void StartServer()

Console.Write(«Write port for accept users: «);

Console.Write(«Write port for receive message: «);

listeningSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); //
Создаем сокет

Task listenTask = new Task(Listen); // Создаем отдельный поток для метода

listenTask.Start(); // Запускаем поток

listenTask.Wait(); // Ожидаем завершения потока

Console.WriteLine(«Error in StartServer(): » + ex.Message);

StopServer(); // Останавливаем сервер

/// Ожидание «подключений» к серверу

private void Listen()

IPEndPoint acceptIP = new IPEndPoint(IPAddress.Parse(«0.0.0.0»), acceptPort); // Создаем конечную точку на которую будут приходить сообщения

StringBuilder builder = new StringBuilder();

byte[] data = new byte[64];

EndPoint senderIP = new IPEndPoint(IPAddress.Any, 0);

bytes = listeningSocket.ReceiveFrom(data, ref senderIP);

builder.Append(Encoding.Unicode.GetString(data, 0, bytes));

while (listeningSocket.Available > 0 && Regex.IsMatch(builder.ToString(), «\\bCODE:[NAME]\\b») == true); // Удостоверяемся, что все данные получены и сообщение содержит метку означающее новое подключение

IPEndPoint senderFullIP = senderIP as IPEndPoint;

// Добавляем пользователя в список «подключенных»

bool addNewUser = true;

bool firstUser = false;

Console.WriteLine(«First connected <0>: <1>his name — <2>«, senderFullIP.Address.ToString(), senderFullIP.Port.ToString(), builder.ToString());

if (firstUser == false)

/// Рассылка сообщений всем пользователям кроме одного

Адрес отправителя ( на этот адрес не будет отправлено сообщение )

public void BroadcastMessage(string message, string address)

/// Добавление клиента в список «подключенных»

Информация о новом клиенте

private void AddUser(IPEndPoint senderFullIP, StringBuilder builder)

User user = new User();

ClientObject client = new ClientObject(this, user, receivePort);

/// Запуск метода для прослушивания данного клиента в отдельном потоке

Клиент для которого запускается отдельный поток

public void UserIsAdded(ClientObject client)

Task clientTask = new Task(client.Listen);

private void StopServer()

if (listeningSocket != null)

Данный класс обеспечивает получение сообщений от каждого «подключенного» пользователя, а после получения сообщения вызывает метод (server.BroadcastMessage()) для рассылки этого сообщения всем остальным «подключенным» клиентам.

int receivePort; // Порт который будет принимать сообщения от данного клиента

public ClientObject(ServerObject _server, User _user, int _port)

/// Прием сообщений от конкретного пользователя

public void Listen()

Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

IPEndPoint receiveIP = new IPEndPoint(IPAddress.Parse(«0.0.0.0»), receivePort);

StringBuilder builder = new StringBuilder();

byte[] data = new byte[64];

EndPoint senderIP = new IPEndPoint(user.FullInfoIP.Address, user.FullInfoIP.Port);

bytes = socket.ReceiveFrom(data, ref senderIP);

builder.Append(Encoding.Unicode.GetString(data, 0, bytes));

while (socket.Available > 0);

А этот класс служит в качестве структуры клиента.

public string Id

public IPEndPoint FullInfoIP

public string Name

Дубликаты не найдены

Перепутал пикабу с гитхаб?

Зачем мистер Андерсен, зачем выкладывать код текстом сюда? Вам мало код-хостингов?

— обработки исключений нет;

— вся многопоточка не потокобезопасна — список users не потокобезопасный, его локать надо! Во время рассылки броадкаста может прилететь от другого клиента и инициировать ещё одну рассылку, хаос! Не помешал бы семафор, мютекс.

— биндинги лучше в конфиг выносить, затрахаешься перекомпилить настройки менять;

— всю логику тогда уж надо строить на передаче сериализованных объектов, а то заибётесь строки парсить;

— каждый клиент на своём порту? Это бред. Портов не хватит. Понятно что их 64к но все равно бред!

Лучше для таких вещей что-то более высокоуровневое использовать, веб-сервисы, например. Это понятней, нагрузки конечно не те, сервер для Eve online вряд-ли запилишь, но работать будет!

Работа с сокетами, основы клиент-серверного приложения

Локально все работает, теперь я хочу чтобы в роли сервера был мой настольный компьютер, а в роли клиента мой ноутбук, или любой другой компьютер подключенный к интернету.
Подскажите какие изменения необходимо внести в исходный код этих файлов, чтоб все заработало. На обоих системах стоит Visual Studio.

23.02.2020, 10:50

Пример клиент-серверного приложения
Может у кого есть пример клиент-сервера передачи текста от клиента к серверу и наоборот? на.

Создание клиент-серверного приложения
Начал изучать С# подскажите как сделать приложение клиент и сервер для отправки сообщений (не на.

Пример клиент-серверного приложения TCP/IP
Здравствуйте, нужен простой и понятный пример клиент-серверного приложения для передачи данных и.

Нужен пример простейшего клиент-серверного приложения
Добрый день. Прчитал примеры в MSDN, скачал книжку Сетевое программироване, но понять пока нечего.

Тестирование клиент-серверного приложения без Thread.Sleep ?
Есть пока что небольшой вебсокет-сервер. При покрытии этого сервера NUnit-тестами передо мной.

24.02.2020, 20:44 [ТС] 2 24.02.2020, 21:05 3

Решение

что означает, что сервер будет принимать соединения с любого IP.

2) В коде клиента переделайте метод SendMessageFromSocket так, что бы он принимал хост удаленного сервера:

28.02.2020, 09:39 [ТС] 4 28.02.2020, 10:54 5

Решение

28.02.2020, 11:09 [ТС] 6

Да у меня стоит роутер, сейчас попробую его отключить и подключить напрямую кабель.

Добавлено через 6 минут
Отлично, есть результат!
Все заработало с моим DDNS, осталось теперь только роутер настроить.

Теперь по другому вопросу, если я хочу, чтобы клиентские приложения соединялись с моим компьютером, то как мне указать им IP который у меня постоянно меняется? Первая мысль которая мне пришла, это в приложении-сервер прописать обновление текстового файла в папке Dropbox в который прописывается текущий IP. Приложения-клиенты первым делом просматривают этот файл (у dropbox при обновлении файла, ссылка не меняется) и пытаются подключиться по указанному в нем IP.

14.02.2020, 21:56 7
14.02.2020, 21:56
14.02.2020, 21:56

Нужен пример клиент-серверного приложения основанный на RPC
Народ, есть у кого пример клиент-серверного приложения основанный на RPC?

Простой пример клиент-серверного приложения использующего распределенные вычисления
Ребят, хелп! Помогите найти доступный для понимания пример распределенных вычислений. То бишь -.

Для данной задачи нужна информации о создании клиент-серверного приложения
Здравствуйте всем. Заранее прошу прощения за данную тему, поскольку эта тему уже ранее обсуждалось.

Purely functional

Страницы

воскресенье, 1 января 2012 г.

Введение в Windows Sockets API: Клиентские сокеты C++

Клиентские сокеты используют приложения, которым необходимо передавать и принимать данные с другим приложением. Примером такого приложения является браузер: по определенному ip-адресу он передает серверу сформированный HTTP-заголовок, в качестве ответа сервер передает данные, которые затребовал в HTTP-заголовке клиент (web-страницу, изображение и т.п.).
В этой статье я расскажу о средствах WSA, необходимых для реализации передачи данных между процессами через клиентские сокеты.

Инициализация WSA

Перед началом работы с сокетами Windows необходимо инициализировать Windows sockets API (WSA)
Для этого надо вызывать функцию WSAStartup и передать в аргументах версию WSA и указатель на структуру WSAData. Функция возвращает 0, если инициализация прошла успешно, в противном случае возвращает код ошибки.

Создание сокета

Функция socket возвращает дескриптор сокета. Если при создании сокета произошла ошибка, она возвращает 0 (INVALID_SOCKET).

Присоединение к серверу

После того как сокет создан, можно начинать подключаться через него к серверам.
Для соединения нужен сам сокет, ip-адрес и порт процесса (сервера). Эти данные передаются функции connect, которая возвращает 0 в случае успешного соединения.
Ip-адрес и порт следует передать структуре sockaddr.

Передача данных серверу

Для передачи данных серверу необходимо вызвать функцию send. Вторым аргументом является указатель на данные, третьим количество данных.
Функция возвращает отрицательное число, если произошла ошибка, иначе возвращается число, соответствующие количеству переданных данных.

Прием данных от сервера

Что бы принять данные надо вызывать функцию recv и передать ей в качестве аргументов указатель на буфер данных и на размер этого буфера.
Из кода видно, что за один раз можно принять не более bufsize байт информации.

Разрыв соединения

Заключение

Дополнительную информацию о функциях, структурах WSA можно найти в MSDN: Winsock reference.

Работа с сокетами в winsock и его аналогами в линукс из Qt

Всем добрый день! Решил я сделать свой клиент-сервер, написал его в дельфи, все работает, коннектится, отвечает. Теперь мне нужно написать клиента под линукс. Выбор пал на Qt. Так как сервер реализован при помощи библиотеки winsock, то и клиент должен использовать ее-же. (верно ли это?), уже знаю, что в линуксе есть ее аналог. Среда разработки выбрана Qt, так как могу писать и отлаживать под виндой, где и работает сервер, а потом перенесу на линукс. В С++ не силен, среды разработки почти не знаю, сейчас учу.

Написал такой код для создания сокета и подключения:

Работа с сокетами на c

Socket (гнездо, разъем) — абстрактное программное понятие, используемое для обозначения в прикладной программе конечной точки канала связи с коммуникационной средой, образованной вычислительной сетью. При использовании протоколов TCP/IP можно говорить, что socket является средством подключения прикладной программы к порту локального узла сети.

Socket-интерфейс представляет собой просто набор системных вызовов и/или библиотечных функций языка программирования СИ, разделенных на четыре группы:

Ниже рассматривается подмножество функций socket-интерфейса, достаточное для написания сетевых приложений, реализующих модель «клиент-сервер» в режиме с установлением соединения. Все функции сокетов содержаться в wsock32.dll перед тем как написать программу с использование функций сокетов необходимо задать компилятору чтобы он включил в программу файл wsock32.lib. В меню Рroject выберите пункт settings а там укажите раздел Link, wsock32.lib можно ввести в поле Library modules или project options. Не забудьте поставить #include «Winsock2.h».

1. Создание сервера

Прежде чем воспользоваться функцией socket необходимо проинициализировать процесс библиотеки wsock32.dll вызвав функцию WSAStartup например: Здесь 0х0101 версия библиотеки которую следует использовать.

Теперь объявление переменную типа SOCKET например s :

    s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

Создание socket’а осуществляется следующим системным вызовом

Аргумент domain задает используемый для взаимодействия набор протоколов (вид коммуникационной области), для стека протоколов TCP/IP он должен иметь символьное значение AF_INET.

Аргумент type задает режим взаимодействия:

  • SOCK_STREAM — с установлением соединения;
  • SOCK_DGRAM — без установления соединения.

Аргумент protocol задает конкретный протокол транспортного уровня (из нескольких возможных в стеке протоколов). Если этот аргумент задан равным 0, то будет использован протокол «по умолчанию» (TCP для SOCK_STREAM и UDP для SOCK_DGRAM при использовании комплекта протоколов TCP/IP).

При удачном завершении своей работы данная функция возвращает дескриптор socket’а — целое неотрицательное число, однозначно его идентифицирующее. Дескриптор socket’а аналогичен дескриптору файла ОС UNIX.

При обнаружении ошибки в ходе своей работы функция возвращает число «-1».

Далее мы задаем параметры для сокета (сервера) для этого нам необходимо объявить структуру SOCKADDR_IN sin далее заполняем параметры для сервера:

Структура SOCKADDR_IN используется несколькими системными вызовами и функциями socket-интерфейса и определена в include-файле in.h следующим образом:

Поле sin_family определяет используемый формат адреса (набор протоколов), в нашем случае (для TCP/IP) оно должно иметь значение AF_INET.

Поле sin_addr содержит адрес (номер) узла сети.

Поле sin_port содержит номер порта на узле сети.

Поле sin_zero не используется.

Определение структуры in_addr (из того же include-файла) таково:

Структура SOCKADDR_IN должна быть полностью заполнена перед выдачей системного вызова bind . При этом, если поле sin_addr.s_addr имеет значение INADDR_ANY, то системный вызов будет привязывать к socket’у номер (адрес) локального узла сети.

Для подключения socket’а к коммуникационной среде, образованной вычислительной сетью, необходимо выполнить системный вызов bind , определяющий в принятом для сети формате локальный адрес канала связи со средой. В сетях TCP/IP socket связывается с локальным портом. Системный вызов bind имеет следующий синтаксис:

Аргумент s задает дескриптор связываемого socket’а.

Аргумент addr в общем случае должен указывать на структуру данных, содержащую локальный адрес, приписываемый socket’у. Для сетей TCP/IP такой структурой является SOCKADDR_IN.

Аргумент addrlen задает размер (в байтах) структуры данных, указываемой аргументом addr.

В случае успеха bind возвращает 0, в противном случае — «-1».

Для установления связи «клиент-сервер» используются системные вызовы listen и accept (на стороне сервера), а также connect (на стороне клиента). Для заполнения полей структуры socaddr_in, используемой в вызове connect , обычно используется библиотечная функция gethostbyname, транслирующая символическое имя узла сети в его номер (адрес).

Системный вызов listen выражает желание выдавшей его программы-сервера ожидать запросы к ней от программ-клиентов и имеет следующий вид:

Пример:

    err = listen( s, SOMAXCONN);

Аргумент s задает дескриптор socket’а, через который программа будет ожидать запросы к ней от клиентов. Socket должен быть предварительно создан системным вызовом socket и обеспечен адресом с помощью системного вызова bind .

Аргумент n определяет максимальную длину очереди входящих запросов на установление связи. Если какой-либо клиент выдаст запрос на установление связи при полной очереди, то этот запрос будет отвергнут.

Признаком удачного завершения системного вызова listen служит нулевой код возврата.

Перед тем как воспользоваться функцией accept сначала объявите ещё одну переменную типа SOCKET, например s1 . Это зделано для того что бы узнать IP адрес и порт удаленного компьютера. Что бы вывести на экран IP адрес и порт удаленного компа просто вставить в программу такие строки:

    printf(«accepted connection from %s, port %d\n», inet_ntoa(from.sin_addr), htons(from.sin_port)) ;

Для приема запросов от программ-клиентов на установление связи в программах-серверах используется системный вызов accept , имеющий следующий вид:

Аргумент s задает дескриптор socket’а, через который программа-сервер получила запрос на соединение (посредством системного запроса listen ).

Аргумент addr должен указывать на область памяти, размер которой позволял бы разместить в ней структуру данных, содержащую адрес socket’а программы-клиента, сделавшей запрос на соединение. Никакой инициализации этой области не требуется.

Аргумент p_addrlen должен указывать на область памяти в виде целого числа, задающего размер (в байтах) области памяти, указываемой аргументом addr.


Системный вызов accept извлекает из очереди, организованной системным вызовом listen , первый запрос на соединение и возвращает дескриптор нового (автоматически созданного) socket’а с теми же свойствами, что и socket, задаваемый аргументом s. Этот новый дескриптор необходимо использовать во всех последующих операциях обмена данными.

Кроме того после удачного завершения accept :

  1. область памяти, указываемая аргументом addr, будет содержать структуру данных (для сетей TCP/IP это sockaddr_in), описывающую адрес socket’а программы-клиента, через который она сделала свой запрос на соединение;
  2. целое число, на которое указывает аргумент p_addrlen, будет равно размеру этой структуры данных.

Если очередь запросов на момент выполнения accept пуста, то программа переходит в состояние ожидания поступления запросов от клиентов на неопределенное время (хотя такое поведение accept можно и изменить).

Признаком неудачного завершения accept служит отрицательное возвращенное значение (дескриптор socket’а отрицательным быть не может).

Примечание. Системный вызов accept используется в программах-серверах, функционирующих только в режиме с установлением соединения.

Вот мы соединились с клиентом, но как получить и передать информацию? Это делается с помощью команд send и recv ко не забывайте что вы теперь работаете с переменной s1: Мы поставили цикл while, потому что он будет выполнятся пока клиент не отключится

Для получения данных от партнера по сетевому взаимодействию используется системный вызов recv , имеющий следующий вид

Аргумент s задает дескриптор socket’а, через который принимаются данные.

Аргумент buf указывает на область памяти, предназначенную для размещения принимаемых данных.

Аргумент len задает длину (в байтах) этой области.

Аргумент flags модифицирует исполнение системного вызова recv . При нулевом значении этого аргумента вызов recv полностью аналогичен системному вызову read .

При успешном завершении recv возвращает количество принятых в область, указанную аргументом buf , байт данных. Если канал данных, определяемый дескриптором s, оказывается «пустым», то recv переводит программу в состояние ожидания до момента появления в нем данных.

Для посылки данных партнеру по сетевому взаимодействию используется системный вызов send , имеющий следующий вид

Аргумент s задает дескриптор socket’а, через который посылаются данные.

Аргумент buf указывает на область памяти, содержащую передаваемые данные.

Аргумент len задает длину (в байтах) передаваемых данных.

Аргумент flags модифицирует исполнение системного вызова send . При нулевом значении этого аргумента вызов send полностью аналогичен системному вызову write .

При успешном завершении send возвращает количество переданных из области, указанной аргументом buf, байт данных. Если канал данных, определяемый дескриптором s, оказывается «переполненным», то send переводит программу в состояние ожидания до момента его освобождения.

Для закрытия ранее созданного socket’а используется обычный системный вызов closesocket , применяемый в ОС UNIX для закрытия ранее открытых файлов и имеющий следующий вид

Аргумент s задает дескриптор ранее созданного socket’а.

Однако в режиме с установлением логического соединения (обеспечивающем, как правило, надежную доставку данных) внутрисистемные механизмы обмена будут пытаться передать/принять данные, оставшиеся в канале передачи на момент закрытия socket’а. На это может потребоваться значительный интервал времени, неприемлемый для некоторых приложений. В такой ситуации необходимо использовать описываемый далее системный вызов shutdown .

2. Создание клиента

Для обращения программы-клиента к серверу с запросом на установление логической соединения используется системный вызов connect , имеющий следующий вид

Аргумент s задает дескриптор socket’а, через который программа обращается к серверу с запросом на соединение. Socket должен быть предварительно создан системным вызовом socket и обеспечен адресом с помощью системного вызова bind .

Аргумент addr должен указывать на структуру данных, содержащую адрес, приписанный socket’у программы-сервера, к которой делается запрос на соединение. Для сетей TCP/IP такой структурой является sockaddr_in. Для формирования значений полей структуры sockaddr_in удобно использовать функцию gethostbyname .

Аргумент addrlen задает размер (в байтах) структуры данных, указываемой аргументом addr.

Для того, чтобы запрос на соединение был успешным, необходимо, по крайней мере, чтобы программа-сервер выполнила к этому моменту системный вызов listen для socket’а с указанным адресом.

При успешном выполнении запроса системный вызов connect возвращает 0, в противном случае — «-1» (устанавливая код причины неуспеха в глобальной переменной errno).

Примечание. Если к моменту выполнения connect используемый им socket не был привязан к адресу посредством bind , то такая привязка будет выполнена автоматически.

Примечание. В режиме взаимодействия без установления соединения необходимости в выполнении системного вызова connect нет. Однако, его выполнение в таком режиме не является ошибкой — просто меняется смысл выполняемых при этом действий: устанавливается адрес «по умолчанию» для всех последующих посылок дейтаграмм.

Вот наконец установлена долгожданная связь c сервером( не забывайте проверять ошибки). Дальше воспользуемся функциями send и recv по своему усмотрению.

3. Приложение

Для получения адреса узла сети TCP/IP по его символическому имени используется библиотечная функция

Аргумент name задает адрес последовательности литер, образующих символическое имя узла сети.

При успешном завершении функция возвращает указатель на структуру hostent, определенную в include-файле netdb.h и имеющую следующий вид

Поле h_name указывает на официальное (основное) имя узла.

Поле h_aliases указывает на список дополнительных имен узла (синонимов), если они есть.

Поле h_addrtype содержит идентификатор используемого набора протоколов, для сетей TCP/IP это поле будет иметь значение AF_INET.

Поле h_lenght содержит длину адреса узла.

Поле h_addr указывает на область памяти, содержащую адрес узла в том виде, в котором его используют системные вызовы и функции socket-интерфейса.

Для «экстренного» закрытия связи с партнером (путем «сброса» еще не переданных данных) используется системный вызов shutdown , выполняемый перед close и имеющий следующий вид

Аргумент s задает дескриптор ранее созданного socket’а.

Аргумент how задает действия, выполняемые при очистке системных буферов socket’а:

7.5. пУОПЧОЩЕ ЖХОЛГЙЙ ДМС ТБВПФЩ У УПЛЕФБНЙ

иПФС FreeBSD РТЕДМБЗБЕФ ТБЪМЙЮОЩЕ ЖХОЛГЙЙ ДМС ТБВПФЩ У УПЛЕФБНЙ, ОБН ЧУЕЗП МЙЫШ РПФТЕВХЕФУС 4 ДМС »ПФЛТЩФЙС», Б Ч ОЕЛПФПТЩИ УМХЮБСИ ФПМШЛП 2 ЖХОЛГЙЙ.

7.5.1. тБЪМЙЮЙЕ НЕЦДХ ЛМЙЕОФПН Й УЕТЧЕТПН

пВЩЮОП ПДОЙН ЙЪ ЛПОГПЧ УПЕДЙОЕОЙС ОБ ПУОПЧЕ УПЛЕФПЧ СЧМСЕФУС УЕТЧЕТ , Б ДТХЗЙН ЛМЙЕОФ .

7.5.1.1. пВЭЙЕ ЬМЕНЕОФЩ

7.5.1.1.1. socket

жХОЛГЙС, ЙУРПМШЪХЕНБС ЛБЛ ЛМЙЕОФПН, ФБЛ Й УЕТЧЕТПН — socket (2) . пОБ ПВЯСЧМЕОБ, ЛБЛ:

чПЪЧТБЭБЕНПЕ ЪОБЮЕОЙЕ ФПЗП ЦЕ ФЙРБ, ЮФП Й Х ЖХОЛГЙЙ open , Ф.Е. ГЕМПЗП. FreeBSD ЧЩДЕМСЕФ ЬФП ЪОБЮЕОЙЕ ЙЪ ФПК ЦЕ ФБВМЙГЩ, ПФЛХДБ ЧЩДЕМСАФУС ЪОБЮЕОЙС ДМС ДЕУЛТЙРФПТПЧ ЖБКМПЧ. ьФБ ЧПЪНПЦОПУФШ РПЪЧПМСЕФ ПФОПУЙФШУС Л УПЛЕФБН, ФБЛЦЕ, ЛБЛ Й Л ЖБКМБН.

бТЗХНЕОФ domain ХЛБЪЩЧБЕФ ОБ УЕНЕКУФЧП РТПФПЛПМПЧ , ЛПФПТПЕ НЩ ИПФЙН ЙУРПМШЪПЧБФШ. оЕЛПФПТЩЕ ЙЪ УХЭЕУФЧХАЭЙИ УЕНЕКУФЧ ЪБЧЙУЙНЩ ПФ ЛПНРБОЙЙ-ТБЪТБВПФЮЙЛБ, ДТХЗЙЕ ПВЭЕЙЪЧЕУФОЩЕ. пОЙ ПВЯСЧМЕОЩ Ч sys/socket.h.

уХЭЕУФЧХЕФ 5 ЪОБЮЕОЙК, ПРТЕДЕМЕООЩИ ДМС БТЗХНЕОФБ type , ПВЯСЧМЕООЩИ Ч ЖБКМЕ sys/socket.h. чУЕ ПОЙ ОБЮЙФБАФУС У » SOCK_ ». оБЙВПМЕЕ ПВЭЙК — SOCK_STREAM , ЛПФПТЩК ЗПЧПТЙФ УЙУФЕНЕ, ЮФП НЩ ИПФЙН ЙУРПМШЪПЧБФШ ОБДЈЦОЩК РПФПЛПЧЩК УЕТЧЙУ ДПУФБЧЛЙ , ЛБЛПЧЩН СЧМСЕФУС TCP РТЙ ЙУРПМШЪПЧБОЙЙ У PF_INET .

SOCK_DGRAM ХЛБЪЩЧБЕФ ОБ ЙУРПМШЪПЧБОЙЕ УЕТЧЙУБ ДПУФБЧЛЙ ДЕКФБЗТБНН ВЕЪ ХУФБОПЧМЕОЙС УПЕДЙОЕОЙС (Ч ОБЫЕН УМХЮБЕ ЬФП UDP ).

й ОБЛПОЕГ, БТЗХНЕОФ protocol ЪБЧЙУЙФ ПФ РТЕДЩДХЭЙИ ДЧХИ БТЗХНЕОФПЧ, Й ОЕ ЧУЕЗДБ СЧМСЕФУС ЪОБЮЙНЩН. ч ЬФПН УМХЮБЕ ЙУРПМШЪХКФЕ ЪОБЮЕОЙЕ 0 .

оЕРТЙУПЕДЙОЈООЩК УПЛЕФ: оЙЗДЕ, РТЙ ЧЩЪПЧЕ ЖХОЛГЙЙ socket , НЩ ОЕ ХЛБЪБМЙ Л ЛБЛПК УЙУФЕНЕ НЩ ИПФЙН РТЙУПЕДЙОЙФШУС. оБЫ ФПМШЛП ЮФП УПЪДБООЩК УПЛЕФ ПУФБЈФУС ОЕРТЙУПЕДЙОЈООЩН .

ьФП БОБМПЗЙЮОП УЙФХБГЙЙ, ЛПЗДБ НЩ РПДЛМАЮЙМЙ НПДЕН Л ФЕМЕЖПООПК МЙОЙЙ Й ОЕ ДБМЙ ЕНХ ОЙ ЛПНБОДХ ДПЪЧПОБ, ОЙ ЛПНБОДХ ПФЧЕФБ ОБ ЧИПДСЭЙЕ ЪЧПОЛЙ.

7.5.1.1.2. sockaddr

тБЪМЙЮОЩЕ ЖХОЛГЙЙ ДМС ТБВПФЩ У УПЛЕФБНЙ РТЕДРПМБЗБАФ ЙУРПМШЪПЧБОЙЕ БДТЕУБ (ХЛБЪБФЕМШ, Ч ФЕТНЙОПМПЗЙЙ СЪЩЛБ у) НБМЕОШЛПЗП ХЮБУФЛБ РБНСФЙ. тБЪМЙЮОЩЕ ПВЯСЧМЕОЙС ЙЪ ЖБКМБ sys/socket.h Ч ЛБЮЕУФЧЕ ЬФПЗП ХЛБЪБФЕМС ЙУРПМШЪХАФ БДТЕУ struct sockaddr . пРЙУБОЙЕ ДБООПК УФТХЛФХТЩ НПЦОП ОБКФЙ Ч ЬФПН ЦЕ ЖБКМЕ:

пВТБФЙФЕ ЧОЙНБОЙЕ ОБ ОЕСУОПУФШ У ЛПФПТПК ПВЯСЧМЕОП РПМЕ sa_data . дБООПЕ РПМЕ РТЕДУФБЧМСЕФ ЧУЕЗП МЙЫШ НБУУЙЧ ЙЪ 14 ВБКФ, У ЛПННЕОФБТЙЕН, ЗПЧПТСЭЙН, ЮФП ОБ УБНПН ДЕМЕ ЛПМЙЮЕУФЧП ВБКФ НПЦЕФ РТЕЧЩЫБФШ 14 .

ьФП ОЕСУОПУФШ ДПЧПМШОП ИПТПЫП РТПДХНБОБ. уПЛЕФЩ ЬФП ПЮЕОШ НПЭОЩК ЙОФЕТЖЕКУ. иПФС НОПЗЙЕ ЧПЪНПЦОП ДХНБАФ, ЮФП ЬФП ОЕ ВПМШЫЕ, ЮЕН Internet ЙОФЕТЖЕКУ—ВПМШЫЙОУФЧП РТЙМПЦЕОЙК ФПЦЕ ЙУРПМШЪХАФ ЙИ—УПЛЕФЩ НПЗХФ ЙУРПМШЪПЧБФШУС ДМС МАВПЗП ЧЙДБ ЧЪБЙНПДЕКУФЧЙК НЕЦДХ РТПГЕУУБНЙ, ЙЪ ЛПФПТЩИ Internet (ЙМЙ, ЕУМЙ ВЩФШ ВПМЕЕ ФПЮОЩН, IP ) ФПМШЛП ПДОБ ТБЪОПЧЙДОПУФШ.

ч ЖБКМЕ sys/socket.h РТЙУХФУФЧХЕФ УРЙУПЛ ТБЪМЙЮОЩИ ФЙРПЧ РТПФПЛПМПЧ, ЛПФПТЩЕ УПЛЕФБНЙ ЙУРПМШЪХАФУС, ЛБЛ БДТЕУОЩЕ УЕНЕКУФЧБ (address families). пО ОБИПДЙФУС РЕТЕД ПРТЕДЕМЕОЙЕН УФТХЛФХТЩ sockaddr :

ьФП БДТЕУОПЕ УЕНЕКУФЧП , ЙУРПМШЪХЕНПЕ Ч РПМЕ sa_family УФТХЛФХТЩ sockaddr , ЛПФПТБС ПРТЕДЕМСЕФ, ЛБЛ ВХДХФ ЙУРПМШЪПЧБФШУС ВБКФЩ ЙЪ sa_data .

лПЗДБ БДТЕУОЩН УЕНЕКУФЧПН СЧМСЕФУС AF_INET НЩ НПЦЕН ЙУРПМШЪПЧБФШ struct sockaddr_in , ПРТЕДЕМЈООХА Ч netinet/in.h ЧНЕУФП sockaddr :

зТБЖЙЮЕУЛЙ ЕЈ ПТЗБОЙЪБГЙА НПЦОП РТЕДУФБЧЙФШ ФБЛ:

фТЙ ЪОБЮЙНЩИ РПМС: sin_family — 1 ВБКФ УФТХЛФХТЩ, sin_port — 16-ВЙФОПЕ ЪОБЮЕОЙЕ, ТБУРПМПЦЕООПЕ ЧП 2 Й 3 ВБКФБИ Й sin_addr — 32-ВЙФОПЕ ГЕМПЕ РТЕДУФБЧМЕОЙЕ IP БДТЕУБ, ЪБОЙНБАЭЕЕ ВБКФЩ У 4 РП 7.

рПМЕ sin_addr ПВЯСЧМЕОП Ч ЧЙДЕ ЪОБЮЕОЙС, ЙНЕАЭЕЗП ФЙР struct in_addr , ЛПФПТЩК ПРТЕДЕМЈО Ч ЖБКМЕ netinet/in.h:

in_addr_t — ЬФП 32-ВЙФОПЕ ГЕМПЕ.

192.43.244.18 — ЬФП ЧУЕЗП МЙЫШ ХДПВОБС ЖПТНБ ЧЩТБЦЕОЙС 32-ВЙФОПЗП ГЕМПЗП, РХФЈН РЕТЕЮЙУМЕОЙС ЧУЕИ ЕЗП ВБКФ, ОБЮЙОБС У УБНПЗП ЪОБЮЙНПЗП .

дП ЬФПЗП НПНЕОФБ НЩ ОЕ УМЙЫЛПН НОПЗП ЧОЙНБОЙС ХДЕМСМЙ sockaddr . оБЫ ЛПНРШАФЕТ ОЕ ИТБОЙФ ЛПТПФЛЙЕ ГЕМЩЕ Ч ЧЙДЕ ПДОПЗП 16-ВЙФОПЗП ПВЯЕЛФБ, Б Ч ЧЙДЕ 2-ВБКФПЧПК РПУМЕДПЧБФЕМШОПУФЙ. бОБМПЗЙЮОП, 32-ВЙФОЩЕ ГЕМЩЕ ИТБОСФУС Ч ЧЙДЕ 4-ВБКФПЧПК РПУМЕДПЧБФЕМШОПУФЙ.

рТЕДРПМПЦЙН, ЮФП НЩ ОБРЙУБМЙ ЮФП-ФП ФЙРБ ЬФПЗП:

лБЛЙН ВХДЕФ ТЕЪХМШФБФ?

дБ, ЛПОЕЮОП ЬФП ЪБЧЙУЙФ ПФ РТЕДУФБЧМЕОЙС ГЕМЩИ. оБ Pentium ® ЙМЙ ОБ ДТХЗПН, ПУОПЧБООПН ОБ x86, ЛПНРШАФЕТЕ ТЕЪХМШФБФ ВХДЕФ УМЕДХАЭЙН:

оБ ДТХЗПК УЙУФЕНЕ ЬФП НПЦЕФ ЧЩЗМСДЕФШ ФБЛ:

оБ PDP ТЕЪХМШФБФ НПЦЕФ ЧЩЗМСДЕФШ РП-ДТХЗПНХ. оП, ДЧБ ЧЩЫЕ РТЙЧЕДЈООЩИ УРПУПВБ ЧУФТЕЮБАФУС ОБЙВПМЕЕ ЮБУФП.

пВЩЮОП, ЦЕМБС ОБРЙУБФШ РЕТЕОПУЙНЩК ЛПД, РТПЗТБННЙУФЩ ОЕ ПВТБЭБАФ ЧОЙНБОЙС ОБ ЬФЙ ТБЪМЙЮЙС Й ОЕ ПВТБВБФЩЧБАФ ЙИ (ЛТПНЕ УМХЮБЕЧ, ЛПЗДБ РТПЗТБННБ РЙЫЕФУС ОБ БУУЕНВМЕТЕ). хЧЩ, ЧЩ ОЕ НПЦЕФЕ МЕЗЛП ПРХУФЙФШ ЬФХ ПВТБВПФЛХ РТЙ РТПЗТБННЙТПЧБОЙЙ УПЛЕФПЧ.

рПФПНХ ЮФП, РТЙ УПЕДЙОЕОЙЙ У ДТХЗЙН ЛПНРШАФЕТПН, ЧЩ ПВЩЮОП ОЕ ЪОБЕФЕ, ИТБОЙФ МЙ ПО ДБООЩЕ, ОБЮЙОБС У УБНПЗП ЪОБЮЙНПЗП ВБКФБ (most significant byte, MSB ) ЙМЙ У ОБЙНЕОЕЕ ЪОБЮЙНПЗП ВБКФБ (least significant byte, LSB ).

чПЪНПЦОП ЧЩ УРТПУЙФЕ: »оЕХЦЕМЙ УПЛЕФЩ ОЕ УДЕМБАФ ЬФП ЪБ НЕОС?»

иПФС ЬФПФ ПФЧЕФ НПЦЕФ ХДЙЧЙФШ ЧБУ, ЪБРПНОЙФЕ, ЮФП ПВЭЙК ЙОФЕТЖЕКУ УПЛЕФПЧ РПОЙНБЕФ ФПМШЛП РПМС sa_len Й sa_family УФТХЛФХТЩ sockaddr . й ЪДЕУШ ЧБН ОЕ ОБДП ВЕУРПЛПЙФШУС П РПТСДЛЕ ВБКФ (ЛПОЕЮОП, ОБ FreeBSD sa_family ЪБОЙНБЕФ ФПМШЛП 1 ВБКФ Ч МАВПН УМХЮБЕ, ОП НОПЗЙЕ ДТХЗЙЕ UNIX ® УЙУФЕНЩ ОЕ ЙНЕАФ РПМС sa_len Й ЙУРПМШЪХАФ 2 ВБКФБ РПД sa_family Й РТЕДРПМБЗБАФ, ЮФП ДБООЩЕ, ОЕЪБЧЙУЙНП ПФ РПТСДЛБ УМЕДПЧБОЙС СЧМСАФУС ТПДОЩНЙ ДМС ЛПНРШАФЕТБ).

оП ПУФБМШОПЕ — РТПУФП sa_data[14] ДП ЛПОГБ ДЕКУФЧЙС ЙОФЕТЖЕКУБ УПЛЕФПЧ. ч ЪБЧЙУЙНПУФЙ ПФ БДТЕУОПЗП УЕНЕКУФЧБ , УПЛЕФЩ РТПУФП РЕТЕУЩМБАФ ЬФЙ ДБООЩЕ Л НЕУФХ ОБЪОБЮЕОЙС.

лПЗДБ НЩ ЧЧПДЙН ОПНЕТ РПТФБ НЩ ИПФЙН, ЮФПВЩ ДТХЗПК ЛПНРШАФЕТ ЪОБМ ЛБЛПК УЕТЧЙУ НЩ ЪБРТБЫЙЧБЕН. й, ЛПЗДБ НЩ СЧМСЕНУС УЕТЧЕТПН, НЩ РПМХЮБЕН ОПНЕТ РПТФБ, ЮФПВЩ ЪОБФШ ЛБЛПК ОБЫ УЕТЧЙУ ЪБРТПУЙМ ДТХЗПК ЛПНРШАФЕТ. ч МАВПН УМХЮБЕ УПЛЕФЩ РЕТЕУЩМБАФ ОПНЕТ РПТФБ Ч ЧЙДЕ ДБООЩИ Й ПОЙ ЕЗП ОЕ ЙОФЕТРТЕФЙТХАФ.

рП ЬФПК РТЙЮЙОЕ, НЩ ( РТПЗТБННЙУФЩ , Б ОЕ УПЛЕФЩ ) ДПМЦОЩ ТБЪМЙЮБФШ РПТСДПЛ ВБКФ (byte order), ЙУРПМШЪХЕНЩК ОБЫЙН ЛПНРШАФЕТПН Й ХУМПЧОЩК РПТСДПЛ ВБКФ, ЙУРПМШЪХЕНЩК ДМС ПФУЩМЛЙ ДБООЩИ ДТХЗПНХ ЛПНРШАФЕТХ.

нЩ ВХДЕН ОБЪЩЧБФШ РПТСДПЛ ВБКФ, ЙУРПМШЪХЕНЩК ОБЫЙН ЛПНРШАФЕТПН — host byte order (РПТСДПЛ ВБКФ ИПУФБ) ЙМЙ РТПУФП host order .

уЕКЮБУ, ЕУМЙ ВЩ НЩ УЛПНРЙМЙТПЧБМЙ ЧЩЫЕ РТЙЧЕДЈООЩК ЛПД ОБ Intel ЛПНРШАФЕТЕ, ФП ОБЫ РПТСДПЛ ВБКФ ИПУФБ ЧЩДБМ ВЩ:

оП УЕФЕЧПК РПТСДПЛ ВБКФ ФТЕВХЕФ РТЕДУФБЧМЕОЙС ДБООЩИ, ОБЮЙОБС У MSB :

л УПЦБМЕОЙА, ОБЫ РПТСДПЛ ВБКФ ИПУФБ ФПЮОБС РТПФЙЧПРПМПЦОПУФШ УЕФЕЧПНХ РПТСДЛХ ВБКФ .

еУФШ ОЕУЛПМШЛП УРПУПВПЧ ПВТБВПФЛЙ ФБЛЙИ НПНЕОФПЧ. уРПУПВ, РТЕДУФБЧМЕООЩК ОЙЦЕ РЕТЕЧПТБЮЙЧБЕФ ЪОБЮЕОЙС Ч ОБЫЕН ЛПДЕ:

ьФБ ИЙФТПУФШ ЪБУФБЧЙФ ЛПНРЙМСФПТБ РПНЕОСФШ РПТСДПЛ ОБ УЕФЕЧПК РПТСДПЛ ВБКФ . ч ОЕЛПФПТЩИ УМХЮБСИ ЬФПФ УРПУПВ ЙУРПМШЪХЕФУС (ОБРТЙНЕТ, РТЙ РТПЗТБННЙТПЧБОЙЙ ОБ БУУЕНВМЕТЕ). пДОБЛП, Ч ВПМШЫЙОУФЧЕ УМХЮБСИ ЬФП НПЦЕФ ЧЩЪЧБФШ РТПВМЕНЩ.

рТЕДРПМПЦЙН, ЮФП ЧЩ ОБРЙУБМЙ РТПЗТБННХ ОБ C, ТБВПФБАЭХА У УПЛЕФБНЙ. чЩ ЪОБЕФЕ, ЮФП ПОБ ВХДЕФ ЪБРХУЛБФШУС ОБ Pentium , Й РПЬФПНХ, РТЙОХДЙФЕМШОП РЕТЕЧЕМЙ ЧУЕ ЛПОУФБОФЩ Ч УЕФЕЧПК РПТСДПЛ ВБКФ . пОБ ТБВПФБЕФ ИПТПЫП.

ъБФЕН, Ч ПДЙО РТЕЛТБУОЩК ДЕОШ, ЧБЫ УФБТЕОШЛЙК Pentium УФБОПЧЙФУС ОЕРТЙЗПДОЩН. чЩ НЕОСЕФЕ ЕЗП ОБ УЙУФЕНХ, Х ЛПФПТПК РПТСДПЛ ВБКФ ИПУФБ УПЧРБДБЕФ У УЕФЕЧЩН РПТСДЛПН ВБКФ . чБН ОХЦОП ВХДЕФ РЕТЕЛПНРЙМЙТПЧБФШ ЧУЈ ЧБЫЕ РТПЗТБННОПЕ ПВЕУРЕЮЕОЙЕ. рПУМЕ ЬФПЗП ЧУЕ РТПЗТБННЩ ВХДХФ РТПДПМЦБФШ ТБВПФБФШ ОПТНБМШОП, ЪБ ЙУЛМАЮЕОЙЕН ОБРЙУБООПК ЧБНЙ.

чЩ ОБЧЕТОСЛБ ЪБВЩМЙ, ЮФП ЙЪНЕОЙМЙ ЧУЕ ЧБЫЙ ЛПОУФБОФЩ ОБ РТПФЙЧПРПМПЦОЩЕ РПТСДЛХ ВБКФ ИПУФБ . чЩ РТПЧПДЙФЕ НОПЗП ЧТЕНЕОЙ, ЧЩТЩЧБС ЧПМПУЩ ОБ ЗПМПЧЕ, ЧЪЩЧБЕФЕ ЛП ЧУЕН ВПЗБН, ЙНЕОБ ЛПФПТЩИ ЧЩ ФПМШЛП УМЩЫБМЙ (ОЕЛПФПТЩИ РТЙДХНБМЙ УБНЙ), ВШЈФЕ РП НПОЙФПТХ ДХВЙОЛПК Й РТПЧПДЙФЕ ДТХЗЙЕ ПВЩЮОЩЕ ГЕТЕНПОЙЙ, УФБТБСУШ РПОСФШ, РПЮЕНХ ЮФП-ФП, ЮФП ТБВПФБМП УФПМШ ИПТПЫП ЧОЕЪБРОП УПЧУЕН РЕТЕУФБЈФ ТБВПФБФШ.

ч ЛПОГЕ ЛПОГПЧ ЧЩ ЪБНЕЮБЕФЕ ПЫЙВЛХ, РТПЙЪОПУЙФЕ ОЕУЛПМШЛП ТХЗБФЕМШОЩИ УМПЧ Й ОБЮЙОБЕФЕ РЕТЕРЙУЩЧБФШ ЛПД.

л УЮБУФША, ЧЩ ОЕ РЕТЧЩК, ЛФП УФБМЛЙЧБЕФУС У ДБООПК РТПВМЕНПК. лФП-ФП ХЦЕ УПЪДБМ ЖХОЛГЙЙ htons (3) Й htonl (3) ДМС РЕТЕЧПДБ ЛПТПФЛЙИ ( short ) Й ДМЙООЩИ ( long ) ЮЙУЕМ, УППФЧЕФУФЧЕООП, ЙЪ РПТСДЛБ ВБКФ ИПУФБ Ч УЕФЕЧПК РПТСДПЛ ВБКФ . жХОЛГЙЙ ntohs (3) Й ntohl (3) ДЕМБАФ ПВТБФОЩК РЕТЕЧПД.

оЕЪБЧЙУЙНП ПФ ФПЗП ОБ ЛБЛПК УЙУФЕНЕ ВЩМБ УЛПНРЙМЙТПЧБОБ ЧБЫБ РТПЗТБННБ, ДБООЩЕ ВХДХФ ТБУРПМБЗБФШУС Ч ОХЦОПН РПТСДЛЕ, ЕУМЙ ЧЩ ВХДЕФЕ ЙУРПМШЪПЧБФШ ЬФЙ ЖХОЛГЙЙ.

7.5.1.2. жХОЛГЙЙ ОБ УФПТПОЕ ЛМЙЕОФБ

7.5.1.2.1. connect

рПУМЕ УПЪДБОЙС ЛМЙЕОФПН УПЛЕФБ ЕЗП ОХЦОП РТЙУПЕДЙОЙФШ Л ПРТЕДЕМЈООПНХ РПТФХ ОБ ХДБМЈООПК УЙУФЕНЕ. дМС ЬФПЗП ЙУРПМШЪХЕФУС connect (2) :

бТЗХНЕОФ s — УПЛЕФ, Ф.Е. ЪОБЮЕОЙЕ, РПМХЮЕООПЕ РПУТЕДУФЧПН ЧЩЪПЧБ socket . name — ХЛБЪБФЕМШ ОБ УФТХЛФХТХ sockaddr , РТП ЛПФПТХА НЩ УФПМШЛП ЗПЧПТЙМЙ. й ОБЛПОЕГ, namelen ЙОЖПТНЙТХЕФ УЙУФЕНХ П ТБЪНЕТЕ УФТХЛФХТЩ sockaddr Ч ВБКФБИ.

еУМЙ connect ЪБЧЕТЫЙМБУШ ХДБЮОП — ЧПЪЧТБЭБЕНПЕ ЪОБЮЕОЙЕ 0 . йОБЮЕ ЧПЪЧТБЭБЕФУС -1 , Й ЛПД ПЫЙВЛЙ УПИТБОСЕФУС Ч errno .

7.5.1.2.2. оБЫ РЕТЧЩК ЛМЙЕОФ

фЕРЕТШ Х ОБУ ДПУФБФПЮОП ЪОБОЙК ДМС ОБРЙУБОЙС РТПУФЕКЫЕЗП ЛМЙЕОФБ, ЛПФПТЩК ВХДЕФ РПМХЮБФШ ФЕЛХЭЕЕ ЧТЕНС У 192.43.244.18 Й ЧЩЧПДЙФШ ЕЗП ОБ stdout.

оБВЕТЙФЕ ФЕЛУФ РТПЗТБННЩ Ч ТЕДБЛФПТЕ, УПИТБОЙФЕ ЕЗП РПД ЙНЕОЕН daytime.c, УЛПНРЙМЙТХКФЕ Й ЪБРХУФЙФЕ:

ч ЬФПН РТЙНЕТЕ РПМХЮЕООБС ДБФБ: 19 йАОС, 2001, a ЧТЕНС 02:29:25 UTC . еУФЕУФЧЕООП ЧБЫЙ ТЕЪХМШФБФЩ ВХДХФ ПФМЙЮБФШУС.

7.5.1.3. жХОЛГЙЙ ОБ УФПТПОЕ УЕТЧЕТБ

фЙРЙЮОЩК УЕТЧЕТ ОЕ ЙОЙГЙЙТХЕФ УПЕДЙОЕОЙЕ. чНЕУФП ЬФПЗП ПО ПЦЙДБЕФ ЛМЙЕОФБ, ЛПФПТЩК ПВТБФЙФУС Л ОЕНХ Й ВХДЕФ ЪБРТБЫЙЧБФШ УЕТЧЙУЩ. пО ОЕ ЪОБЕФ ОЙ ЛПЗДБ ЛМЙЕОФ ПВТБФЙФУС, ОЙ ЛБЛ НОПЗП НОПЗП ВХДЕФ ЛМЙЕОФПЧ. пО НПЦЕФ РТПУФП УЙДЕФШ Й ФЕТРЕМЙЧП ЦДБФШ. уРХУФС ОЕЛПФПТПЕ ЧТЕНС ПО НПЦЕФ ПВОБТХЦЙФШ, ЮФП ЕНХ ОХЦОП ПВТБВПФБФШ ОЕУЛПМШЛП ЪБРТПУПЧ, РПУМБООЩИ Ч ПДОП ЧТЕНС.

йОФЕТЖЕКУ УПЛЕФПЧ РТЕДМБЗБЕФ ФТЙ ПУОПЧОЩИ ЖХОЛГЙЙ ДМС ПВЕУРЕЮЕОЙС ДБООЩИ ДЕКУФЧЙК.

7.5.1.3.1. bind

рПТФЩ НПЦОП РТЕДУФБЧЙФШ Ч ЧЙДЕ БВПОЕОФПЧ ПЖЙУОПК НЙОЙ-бфу: РПУМЕ ФПЗП, ЛБЛ ЧЩ ДПЪЧПОЙМЙУШ, ЧЩ ОБВЙТБЕФЕ ДПРПМОЙФЕМШОЩК ОПНЕТ, ЮФПВЩ УПЕДЙОЙФШУС У ОХЦОЩН ЮЕМПЧЕЛПН ЙМЙ ДЕРБТФБНЕОФПН.

рТЕДРПМПЦЙН, ЮФП НЩ РЙУБМЙ ВЩ УЕТЧЕТ ДМС daytime РТПФПЛПМБ, ТБВПФБАЭЙК ЮЕТЕЪ TCP /IP . йУРПМШЪХЕНЩК РПТФ — 13. оБЫБ УФТХЛФХТБ sockadd_in ЧЩЗМСДЕМБ ВЩ ФБЛ:

7.5.1.3.2. listen

рТПДПМЦБЕН РТПЧПДЙФШ БОБМПЗЙА У ФЕМЕЖПОПН. рПУМЕ ФПЗП, ЛБЛ ЧЩ УППВЭЙМЙ ГЕОФТБМШОПНХ ФЕМЕЖПООПНХ ПРЕТБФПТХ РП ЛБЛПНХ ОПНЕТХ ЧЩ ВХДЕФЕ ДПУФХРОЩ, ЧЩ ЙДЈФЕ Ч УЧПК ПЖЙУ Й ХВЕЦДБЕФЕУШ, ЮФП ЧБЫ ФЕМЕЖПО РПДЛМАЮЈО Й ЪЧПОПЛ ОЕ ЧЩЛМАЮЕО. дПРПМОЙФЕМШОП ЧЩ РТПЧЕТСЕФЕ, ЮФП ЧБЫБ УЙУФЕНБ ПЦЙДБОЙС ЪЧПОЛБ БЛФЙЧЙТПЧБОБ, Й ФЕРЕТШ ЧЩ УНПЦЕФЕ ХУМЩЫБФШ ЪЧПОПЛ ФЕМЕЖПОБ ДБЦЕ ЛПЗДБ У ЛЕН-ФП ТБЪЗПЧБТЙЧБЕФЕ.

уЕТЧЕТ РТПЧЕТСЕФ ЧУЈ ЬФП У РПНПЭША ЖХОЛГЙЙ listen (2) .

рЕТЕНЕООБС backlog УППВЭБЕФ УПЛЕФБН ЛБЛПЕ ЛПМЙЮЕУФЧП ЧИПДСЭЙИ ЪБРТПУПЧ РТЙОЙНБФШ, РПЛБ ЧЩ ЪБОСФЩ ПВТБВПФЛПК РПУМЕДОЕЗП ЪБРТПУБ. дТХЗЙНЙ УМПЧБНЙ, ПО ПРТЕДЕМСЕФ НБЛУЙНБМШОЩК ТБЪНЕТ ПЮЕТЕДЙ ТБУУНБФТЙЧБЕНЩИ УПЕДЙОЕОЙК.

7.5.1.3.3. accept

рПУМЕ ФПЗП, ЛБЛ ЧЩ УМЩЫЙФЕ ФЕМЕЖПООЩК ЪЧПОПЛ — ЧЩ ВЕТЈФЕ ФТХВЛХ. чЩ ФПМШЛП ЮФП УПЪДБМЙ УПЕДЙОЕОЙЕ У ЧБЫЙН ЛМЙЕОФПН. пОП ВХДЕФ РТПДПМЦБФШУС ДП ФЕИ РПТ, РПЛБ ЧЩ ЙМЙ ЧБЫ ЛМЙЕОФ ОЕ РПМПЦЙФ ФТХВЛХ.

уЕТЧЕТ РТЙОЙНБЕФ УПЕДЙОЕОЙС РХФЈН ЙУРПМШЪПЧБОЙС ЖХОЛГЙЙ accept (2) .

ъБНЕФШФЕ, ЮФП Ч ЬФПФ ТБЪ addrlen ЬФП ХЛБЪБФЕМШ. ьФП ОЕПВИПДЙНП РПФПНХ, ЮФП Ч ЬФПФ ТБЪ ЙУРПМШЪХЕНЩК УПЛЕФ ЪБРПМОСЕФ addr , УФТХЛФХТХ sockaddr_in .

чПЪЧТБЭБЕНПЕ ЪОБЮЕОЙЕ ГЕМПЗП ФЙРБ. оБ УБНПН ДЕМЕ, accept ЧПЪЧТБЭБЕФ ОПЧЩК УПЛЕФ . чЩ ВХДЕФЕ ЙУРПМШЪПЧБФШ ЕЗП ДМС УПЕДЙОЕОЙС У ЛМЙЕОФПН.

юФП РТПЙУИПДЙФ УП УФБТЩН УПЛЕФПН? пО РТПДПМЦБЕФ ПЦЙДБФШ ОПЧЩИ ЪБРТПУПЧ (ЧУРПНОЙМЙ РЕТЕНЕООХА backlog , ЛПФПТХА НЩ РЕТЕДБЧБМЙ listen ?) ДП ФЕИ РПТ, РПЛБ НЩ ОЕ ЪБЛТПЕН ЕЗП.

фЕРЕТШ ОПЧЩК УПЛЕФ РТЕДОБЪОБЮЕО ФПМШЛП ДМС ЛПННХОЙЛБГЙК. пО РПМОПУФША РТЙУПЕДЙОЈО. нЩ ОЕ НПЦЕН ЪБОПЧП РЕТЕДБФШ ЕЗП ЖХОЛГЙЙ listen , РЩФБСУШ РТЙОСФШ ДПРПМОЙФЕМШОЩЕ УПЕДЙОЕОЙС.

7.5.1.3.4. оБЫ РЕТЧЩК УЕТЧЕТ

оБЫ РЕТЧЩК УЕТЧЕТ ПФЮБУФЙ ВХДЕФ УМПЦОЕЕ ЛМЙЕОФБ: ОЕ ФПМШЛП РПФПНХ, ЮФП НЩ ВХДЕН ЙУРПМШЪПЧБФШ ВПМШЫЕ ЖХОЛГЙК ДМС ТБВПФЩ У УПЛЕФБНЙ, ОП ЕЭЈ ПО ДПМЦЕО ВЩФШ ДБЕНПОПН.

ьФП МХЮЫЕ ЧУЕЗП ДПУФЙЗБЕФУС УПЪДБОЙЕН РТПГЕУУБ-ТЕВЈОЛБ РПУМЕ УЧСЪЩЧБОЙС РПТФБ. зМБЧОЩК РТПГЕУУ ЪБФЕН ЧЩИПДЙФ Й ЧПЪЧТБЭБЕФ ХРТБЧМЕОЙЕ shell (ЙМЙ МАВПК ДТХЗПК РТПЗТБННЕ, ЛПФПТБС ЕЗП ЪБРХУФЙМБ).

тЕВЈОПЛ ЧЩЪЩЧБЕФ listen , РПФПН ОБЮЙОБЕФ ВЕУЛПОЕЮОЩК ГЙЛМ, ЧП ЧТЕНС ЛПФПТПЗП ПО РТЙОЙНБЕФ УПЕДЙОЕОЙЕ, ПВУМХЦЙЧБЕФ ЕЗП Й Ч ЛПОЕЮОПН УЮЈФЕ ЪБЛТЩЧБЕФ УПЛЕФ.

ч ОБЮБМЕ РТПЗТБННЩ УПЪДБЈФУС УПЛЕФ. ъБФЕН НЩ ЪБРПМОСЕН УФТХЛФХТХ sockaddr_in , ПВЯСЧМЕООХА, ЛБЛ sa . пВТБФЙФЕ ЧОЙНБОЙЕ ОБ ХУМПЧОПЕ ЙУРПМШЪПЧБОЙЕ INADDR_ANY :

еЈ ЪОБЮЕОЙЕ ТБЧОП 0 . фПМШЛП ЮФП, У РПНПЭША bzero НЩ ПВОХМЙМЙ ЧУА УФТХЛФХТХ, Й ВХДЕФ ЙЪМЙЫОЙН ЪБОПЧП РТЙУЧБЙЧБФШ 0 . оП, ЕУМЙ РПТФЙТХЕН ОБЫ ЛПД ОБ ДТХЗХА УЙУФЕНХ, ЗДЕ INADDR_ANY ЧПЪНПЦОП ОЕ ТБЧОСЕФУС ОХМА, ФП НЩ ДПМЦОЩ РТЙУЧПЙФШ ЕЗП sa.sin_addr.s_addr . вПМШЫЙОУФЧП УПЧТЕНЕООЩИ ЛПНРЙМСФПТПЧ СЪЩЛБ у ДПУФБФПЮОП ХНОЩ, ЮФПВЩ ЪБНЕФЙФШ, ЮФП INADDR_ANY — ЛПОУФБОФБ, Й ЕУМЙ ПОБ ТБЧОБ ОХМА, ФП ПОЙ РПМОПУФША ХВЕТХФ ХУМПЧОПЕ ЧЩТБЦЕОЙЕ.

рПУМЕ ХДБЮОПЗП ЪБЧЕТЫЕОЙС bind НЩ ЗПФПЧЩ УФБФШ ДБЕНПОПН : НЩ ЙУРПМШЪХЕН fork ДМС УПЪДБОЙС РТПГЕУУБ-ТЕВЈОЛБ. й Ч ТПДЙФЕМШУЛПН, Й Ч РПТПЦДЈООПН РТПГЕУУБИ РЕТЕНЕООБС s ВХДЕФ УПЛЕФПН. тПДЙФЕМШУЛПНХ РТПГЕУУХ ПО ОЕ ВХДЕФ ОХЦЕО, РПЬФПНХ ПО ЪБЛТЩЧБЕФ ЕЗП, Б ЪБФЕН ЧПЪЧТБЭБЕФ 0 ДМС ЙОЖПТНЙТПЧБОЙС УПВУФЧЕООПЗП ТПДЙФЕМШУЛПЗП РТПГЕУУБ П УЧПЈН ХДБЮОПН ЪБЧЕТЫЕОЙЙ.

фЕН ЧТЕНЕОЕН РПТПЦДЈООЩК РТПГЕУУ РТПДПМЦБЕФ ТБВПФБФШ Ч ЖПОПЧПН ТЕЦЙНЕ. пО ЧЩЪЩЧБЕФ listen Й ХУФБОБЧМЙЧБЕФ ЛПМЙЮЕУФЧП ТБУУНБФТЙЧБЕНЩИ УПЕДЙОЕОЙК 4 . оЕ ОХЦОП ХУФБОБЧМЙЧБФШ ВПМШЫПЕ ЪОБЮЕОЙЕ, ФБЛ ЛБЛ daytime ОЕ ФПФ РТПФПЛПМ, Л ЛПФПТПНХ ЮБУФП ПВТБЭБЕФУС ВПМШЫПЕ ЛПМЙЮЕУФЧП ЛМЙЕОФПЧ, Й ПО УНПЦЕФ ПВТБВПФБФШ ЛБЦДЩК ЪБРТПУ НЗОПЧЕООП.

й ОБЛПОЕГ, ДБЕНПО ОБЮЙОБЕФ ВЕУЛПОЕЮОЩК ГЙЛМ, ЧП ЧТЕНС ЛПФПТПЗП ЧЩРПМОСАФУС УМЕДХАЭЙЕ ЫБЗЙ:

чЩЪЩЧБЕФУС accept . уЕТЧЕТ ЦДЈФ РПЛБ ОЕ РПСЧЙФУС ЛМЙЕОФ. оБ ЬФПН ЫБЗЕ УПЪДБЈФУС ОПЧЩК УПЛЕФ c , ЛПФПТЩК ЙУРПМШЪХЕФУС ДМС УПЕДЙОЕОЙС У ЬФЙН ЛПОЛТЕФОЩН ЛМЙЕОФПН.

пО ЙУРПМШЪХЕФ ЖХОЛГЙА fdopen ДМС РТЕПВТБЪПЧБОЙС ОЙЪЛПХТПЧОЕЗП ЖБКМПЧПЗП ДЕУЛТЙРФПТБ Л ХЛБЪБФЕМА FILE . ьФП РПЪЧПМЙФ Ч ДБМШОЕКЫЕН ЙУРПМШЪПЧБФШ ЖХОЛГЙА fprintf .

нЩ НПЦЕН ПВПВЭЙФШ ЬФЙ ЫБЗЙ Й ЙУРПМШЪПЧБФШ ЙИ, ЛБЛ НПДЕМШ ДМС НОПЗЙИ ДТХЗЙИ УЕТЧЕТПЧ:

ьФБ ВМПЛ-УИЕНБ ИПТПЫП РПДИПДЙФ ДМС РПУМЕДПЧБФЕМШОЩИ УЕТЧЕТПЧ , Ф.Е. УЕТЧЕТПЧ, ЛПФПТЩЕ НПЗХФ ПВУМХЦЙЧБФШ ПДОПЗП ЛМЙЕОФБ Ч ПДОП Й ФПЦЕ ЧТЕНС (РТЙНЕТ: ОБЫ daytime УЕТЧЕТ). ьФП ЧПЪНПЦОП, ФПМШЛП ФПЗДБ, ЛПЗДБ ОЕФ ТЕБМШОПЗП »ТБЪЗПЧПТБ» НЕЦДХ ЛМЙЕОФПН Й УЕТЧЕТПН: РПУМЕ ФПЗП, ЛБЛ УЕТЧЕТ ПРТЕДЕМЙМ УПЕДЙОЕОЙЕ У ЛМЙЕОФПН, ПО РЕТЕУЩМБЕФ ОЕЛПФПТЩЕ ДБООЩЕ Й ЪБЛТЩЧБЕФ УПЕДЙОЕОЙЕ. рПМОБС ПРЕТБГЙС НПЦЕФ ЪБОСФШ ОБОПУЕЛХОДЩ.

рТЕЙНХЭЕУФЧП ДБООПК ВМПЛ-УИЕНЩ Ч ФПН, ЮФП РПЮФЙ ЧУЕЗДБ ФПМШЛП ПДЙО РТПГЕУУ СЧМСЕФУС БЛФЙЧОЩН, ЪБ ЙУЛМАЮЕОЙЕН ОЕВПМШЫПЗП РТПНЕЦХФЛБ НЕЦДХ ЧЩЪПЧПН РТПГЕУУПН-ТПДЙФЕМЕН fork Й ЕЗП ЧЩИПДПН, Ф.Е. ОБЫ УЕТЧЕТ ОЕ ФТЕВХЕФ ВПМШЫПЗП ЛПМЙЮЕУФЧБ РБНСФЙ Й ДТХЗЙИ ТЕУХТУПЧ УЙУФЕНЩ.

пВТБФЙФЕ ЧОЙНБОЙЕ ОБ РХОЛФ initialize daemon Ч ОБЫЕК ВМПЛ-УИЕНЕ. оБН ОЕ ОХЦОП ЙОЙГЙБМЙЪЙТПЧБФШ ОБЫЕЗП ДБЕНПОБ, ОП ЬФП ИПТПЫЕЕ НЕУФП Ч РТПГЕУУЕ ЧЩРПМОЕОЙС РТПЗТБННЩ ДМС ХУФБОПЧЛЙ МАВЩИ ПВТБВПФЮЙЛПЧ УЙЗОБМПЧ , ПФЛТЩФЙС ОХЦОЩИ ЖБКМПЧ Й Ф.Д.

рПЮФЙ ЧУЕ РХОЛФЩ ЙЪ ЬФПК ВМПЛ-УИЕНЩ РТЙНЕОЙНЩ ЛП НОПЗЙН ТБЪМЙЮОЩН УЕТЧЕТБН. йУЛМАЮЕОЙЕ — serve . ьФП ЧТПДЕ ОЕЛПК »ЮЕТОПК ЛПТПВЛЙ» , Ф.Е. ЮФП-ФП, ЮФП ЧЩ РТЙДХНБМЙ УРЕГЙБМШОП ДМС ЧБЫЕЗП УЕТЧЕТБ Й РТПУФП »РПДЛМАЮБЕФЕ Л ПУФБМШОПНХ».

оЕ ЧУЕ РТПФПЛПМЩ ФБЛЙЕ РТПУФЩЕ. нОПЗЙЕ РПМХЮБАФ ЪБРТПУ ПФ ЛМЙЕОФБ, ПФЧЕЮБАФ ОБ ОЕЗП, ЪБФЕН РПМХЮБАФ ДТХЗПК ЪБРТПУ ПФ ЬФПЗП ЦЕ ЛМЙЕОФБ. йЪ-ЪБ ЬФПЗП, ПОЙ ОЕ ЪОБАФ ЛБЛ ДПМЗП ЙН РТЙДЈФУС ПВУМХЦЙЧБФШ ЛМЙЕОФБ. фБЛЙЕ УЕТЧЕТЩ ПВЩЮОП ЪБРХУЛБАФ ОПЧЩК РТПГЕУУ ДМС ЛБЦДПЗП ЛМЙЕОФБ. рПЛБ ОПЧЩК РТПГЕУУ ПВУМХЦЙЧБЕФ ЛМЙЕОФБ, ДБЕНПО НПЦЕФ РТПДПМЦБФШ ЦДБФШ ОПЧЩИ ЪБРТПУПЧ ОБ УПЕДЙОЕОЙЕ.

уПИТБОЙФЕ ЧЩЫЕРТЙЧЕДЈООЩК ЛПД УЕТЧЕТБ Ч daytimed.c (ЙНЕОБ ДБЕНПОПЧ РТЙОСФП ЪБЛБОЮЙЧБФШ ВХЛЧПК d ). рПУМЕ ФПЗП, ЛБЛ ЧЩ УЛПНРЙМЙТПЧБМЙ УЕТЧЕТ, РПРЩФБКФЕУШ ЕЗП ЪБРХУФЙФШ:

юФП ЪДЕУШ УМХЮЙМПУШ? лБЛ ЧЩ РПНОЙФЕ, РТПФПЛПМ daytime ЙУРПМШЪХЕФ 13 РПТФ. оП ЧУЕ РПТФЩ ОЙЦЕ 1024 ЪБТЕЪЕТЧЙТПЧБОЩ ДМС ЪБРХУЛБ УХРЕТРПМШЪПЧБФЕМЕН, ЙОБЮЕ МАВПК НПЦЕФ ЪБРХУФЙФШ ДБЕНПО, ПВУМХЦЙЧБАЭЙК ПВЭЕ-ЙУРПМШЪХЕНЩК РПТФ, ПВТБЪПЧБЧ ВТЕЫШ Ч ВЕЪПРБУОПУФЙ.

рПРЩФБКФЕУШ УОПЧБ, Ч ЬФПФ ТБЪ, ЛБЛ УХРЕТРПМШЪПЧБФЕМШ:

юФП. оЙЮЕЗП ОЕ РТПЙУИПДЙФ? дБЧБКФЕ РПРТПВХЕН ЕЭЈ ТБЪ:

лБЦДЩК РПТФ НПЦЕФ ВЩФШ УЧСЪБО ФПМШЛП У ПДОПК РТПЗТБННПК Ч ПДОП Й ФПЦЕ ЧТЕНС. оБЫБ РЕТЧБС РПРЩФЛБ ОБ УБНПН ДЕМЕ ВЩМБ ХДБЮОБС: ПОБ ЪБРХУФЙМБ ДЙФС-ДБЕНПОБ Й ОЕЪБНЕФОП ЧЕТОХМБ ХРТБЧМЕОЙЕ. дБЕНПО РТПДПМЦБЕФ ТБВПФБФШ ДП ФЕИ РПТ РПЛБ МЙВП ЧЩ ЕЗП ОЕ ХВШЈФЕ, МЙВП ОЕХДБЮОП ЪБЧЕТЫЙФУС ПДЙО ЙЪ УЙУФЕНОЩИ ЧЩЪПЧПЧ, МЙВП РПЛБ ЧЩ ОЕ РЕТЕЪБЗТХЪЙФЕ УЙУФЕНХ.

иПТПЫП, НЩ ЪОБЕН, ЮФП РТПЗТБННБ ЪБРХЭЕОБ Ч ЖПОПЧПН ТЕЦЙНЕ. оП ТБВПФБЕФ МЙ ПОБ? лБЛ ОБН ХЪОБФШ, ЮФП ЬФП РТБЧЙМШОЩК daytime УЕТЧЕТ? рТПУФП:

еУМЙ Х ЧБУ ЕУФШ ДПУФХР Л ДТХЗПК UNIX УЙУФЕНЕ ЮЕТЕЪ telnet, ЧЩ НПЦЕФЕ РТПФЕУФЙТПЧБФШ ДПУФХР Л УЕТЧЕТХ ХДБМЈООП. нПК ЛПНРШАФЕТ ОЕ ЙНЕЕФ УФБФЙЮЕУЛПЗП IP БДТЕУБ, Й ЧПФ, ЮФП С УДЕМБМ:

тБВПФБЕФ. рТПЧЕТЙН, ВХДЕФ МЙ ПОБ ТБВПФБФШ, ЕУМЙ НЩ ЧЧЕДЈН ЙНС ДПНЕОБ?

telnet ЧЩЧПДЙФ УППВЭЕОЙЕ Connection closed by foreign host РПУМЕ ФПЗП, ЛБЛ ОБЫ ДБЕНПО ЪБЛТЩЧБЕФ УПЛЕФ. ьФП РПЛБЪЩЧБЕФ ОБН, ЮФП fclose(client); ТБВПФБЕФ ЛБЛ ОБДП.

рТЕД. оБЮБМП уМЕД.
нПДЕМШ УПЛЕФПЧ хТПЧЕОШ ЧЩЫЕ чУРПНПЗБФЕМШОЩЕ ЖХОЛГЙЙ

рП ЧПРТПУБН, УЧСЪБООЩН У FreeBSD, РТПЮЙФБКФЕ ДПЛХНЕОФБГЙА РТЕЦДЕ ЮЕН РЙУБФШ Ч .
рП ЧПРТПУБН, УЧСЪБООЩН У ЬФПК ДПЛХНЕОФБГЙЕК, РЙЫЙФЕ .
рП ЧПРТПУБН, УЧСЪБООЩН У ТХУУЛЙН РЕТЕЧПДПН ДПЛХНЕОФБГЙЙ, РЙЫЙФЕ Ч ТБУУЩМЛХ .
йОЖПТНБГЙС РП РПДРЙУЛЕ ОБ ЬФХ ТБУУЩМЛХ ОБИПДЙФУС ОБ УБКФЕ РТПЕЛФБ РЕТЕЧПДБ.

как работать с сокетами c ++ через интернет?

Итак, я изучал программирование сокетов в c ++ и могу успешно создать базовое клиент-серверное приложение сокетов, которое работает на локальном компьютере, но я не знаю, как заставить его работать через Интернет, например, создать приложение для чата или что-то похожее, я видел, как люди говорили о перфорации стены UDP для использования интернет-сокетов, но я не могу найти какую-либо информацию или учебное пособие о том, как это сделать.

Решение

Делайте это так же, как вы делали это на своей локальной машине.

Розетки — это розетки. Это скорее весь смысл.

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

Понятия не имею, что такое «перфорация стены UDP» или где это происходит.

Любая дополнительная информация потребует схемы вашей сети и подробного плана для предполагаемого варианта использования.

Склад программиста. C C++ Pascal Java и Assembler Исходники

Паскаль исходники. Паскаль программы. Pascal исходники. Pascal программы. С программы исходники. Исходники ассемблер. Ассемблер задачи. Си программы. Исходники Паскаль. Исходники C. Исходники Си. Си программы. Си исходники. Си задачи. Паскаль задачи. Задачи на паскале. Задачи по паскале. Решить задачу по паскалю. Бесплатные исходники. Скачать бесплатно исходники. Бесплатные программы. Исходники C++, исходники СИ++. Скачать бесплатно исходники. Исходники бесплатно. Java исходники. Java классы.

28 мая 2009 г.

Сокеты на C/C++

Cокеты(sockets) представляют собой высокоуровневый унифицированный интерфейс взаимодействия с телекоммуникационными протоколами. Програмировать сокеты несложно, в Windows и UNIX програмирование сокетов имеет значительное отличие, из-за чего у новичков на начальных этапах освоения сокетов появляеться масса проблем.

Свой первый цикл статей я посвящу только одной реализации сокетов — Winsock2. Библиотека Winsock поддерживает два вида сокетов синхронные и асинхронные. Синхронные сокеты задерживают управление на время выполнения операции, а Асинхронные — возвращают его немедленно, продолжая работать в фоновом режиме.

Сокеты, независимо от вида, деляться на три типа: потоковые, сырые(windows их не «держит») и дейтаграммные. Потоковые сокеты работают с установкой соединения, обеспечивая надежную идентификацию обеих сторон и гарантируют целостность и успешность доставки данных,опираються на протокол TCP. Дейтаграммные сокеты работают без установки соединения и не обеспечивают ни идентификации отправителя, ни контроля успешности доставки данных, зато они быстрее потоковых, опираються на протокол UDP. Сырые сокеты, они предоставляют возможность ручного формирования TCP\IP пакетов.

Програмирование сокетов идет поэтапно:

1.Создание сокета
2.Привязка сокета к локальным именам
3.Установка связи
4.Передача данных
5.Закрытие сокета

Ну, кто еще не знает, как работать с сокетами я опишу на создании простенького TCP-клиента. Это программа для тех, кто уже хоть немного знаком с языком С++. Надеюсь все помнят, что символ // обозначает коментарии и никак не влияет на действие программы.

#include
#include
// Для работы с библиотекой Winsock2 в исходный текст нужно включить директиву #include ,
//а в командной строке компоновщика указать ws2_32.lib. Библиотека Winsock2 должна быть указана раньше,
// чем библиотека Windows.
#include
#include

#define PORT 31337 // Порт, через который идет подключение к серверу. 21,80,25,110 и т.п.
#define SERVERADDR «127.0.0.1» // Адрес сервера

int main ( int argc, char* argv [ ] )
<
char buff [ 1024 ] ;
printf ( «TCP Client \n» ); // ну, тут и так понятно
//Перед началом использования библиотеки ее необходимо подготовить к работе с помощью вызова функции
// WSAStartup(Ver, lpWSAData), передав ей в старшем байте номер требуемой версии, а в младшем подверсии.
// Аргумент lpWSAData должен указывать на структуру WSADATA, в которую при успешной инициализации
//будет занесена информация о производителе библиотеки. Если инициализация не удалась, то функция //возвращает не нулевое значение.
if ( WSAStartup ( 0x202, ( WSADATA * ) &buff [ 0 ] ) )
<
printf ( » WSAStart error %d \n «, WSAGetLastError ( ) );
return -1;
>
// Создаем сокет socket ( int af, int type, int protocol ). Первый слева аргумент указывает на семейство использу-
//емых протоколов, AF_INET — используеться при создании интернет приложений. SOCK_STREAM — тип //создаваемого сокета, SOCK_STREAM (потоковый) или SOCK_DGRAM (дейтаграммный) или SOCK_RAW //(сырой).Последний аргумент задает тип создаваемого сокета, нулевое значение соответствует выбору по //умолчанию, ТСР — для потоковых, и UDP — дейтограммных.
//Если функция завершилась успешно то она возвращает дескриптор сокета.
SOCKET my_sock ;
my_sock=socket ( AF_INET, SOCK_STREAM, 0 );
if ( my_sock h_addr_list содержит массив указателей на адреса, НО не массив адресов
( ( unsigned long ** ) hst->h_addr_list ) [ 0 ] [ 0 ] ;
//Если ip-адрес не получен, то работа программы завершаеться
else
<
printf ( » invalid address %s \n «, SERVERADDR ) ;
closesocket ( my_sock ) ;
WSACleanup ( ) ;
return -1;
>
//После получения адреса сервера, попытаемся установит соединение.Для этого мы вызовем функцию connect
// (SOCKET s, sockaddr * name, len). Первый элемент -SOCKET- это дескриптор сокета, второй —
//указатель на структуру sockaddr, содержащую в себе адрес (ip) и порт, последний аргумент сообщает о размере
// sockaddr.
// Если по каким-то причинам установить соединение не удаеться, то функция возвращает не нулевое значение.
if (connect ( my_sock, ( sockaddr * ) &dest_addr, sizeof ( dest_addr ) ) )
<
printf (» Connect error %d \n «, WSAGetLastError ( ) );
return -1;
>

printf (» Соединение с %s успешно установлено \n\ Type quit for quit \n\n» , SERVERADDR );
//Далее начинаеться чтение и передача сообщений.
int nsize;
while ( ( nsize = recv ( my_sock, &buff[0], sizeof ( buff ) -1,0 ) ) !=SOCKET_ERROR )
<
//Ставим завершающий ноль в конце строки
buff[ nsize ] =0;
//Выводим на экран
printf ( » S=>C: %s «, buff ) ;
//Читаем пользовательский ввод с клавиатуры
printf ( «S

Илон Маск рекомендует:  22 способа создать цепляющий контент, когда у вас нет идей
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL