Light-electric.com

IT Журнал
2 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Сетевое программирование си

Программирование сокетов на C / C ++

Что такое сокет программирования?
Сокетное программирование — это способ соединения двух узлов в сети для связи друг с другом. Один сокет (узел) прослушивает определенный порт с IP-адреса, а другой сокет обращается к другому, чтобы сформировать соединение. Сервер формирует сокет слушателя, в то время как клиент обращается к серверу.

Диаграмма состояний для модели сервера и клиента

Этапы для сервера

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

sockfd: дескриптор сокета, целое число (как дескриптор файла)
домен: целое число, домен связи, например, AF_INET (протокол IPv4), AF_INET6 (протокол IPv6)
тип: тип связи
SOCK_STREAM: TCP (надежный, ориентированный на соединение)
SOCK_DGRAM: UDP (ненадежный, без установления соединения)
protocol: значение протокола для интернет-протокола (IP), равное 0. Это то же число, которое указывается в поле протокола в заголовке IP пакета.

Setsockopt:

Это помогает в манипулировании опциями для сокета, на который ссылается дескриптор файла sockfd. Это совершенно необязательно, но помогает в повторном использовании адреса и порта. Предотвращает ошибку, такую как: «адрес уже используется».

Bind:

После создания сокета функция bind связывает сокет с адресом и номером порта, указанными в addr (пользовательская структура данных). В примере кода мы привязываем сервер к локальному узлу, поэтому мы используем INADDR_ANY для указания IP-адреса.

Слушать:

Он переводит сокет сервера в пассивный режим, в котором он ждет, пока клиент подойдет к серверу, чтобы установить соединение. Журнал ожидания определяет максимальную длину, до которой может увеличиваться очередь ожидающих соединений для sockfd. Если запрос на подключение приходит, когда очередь заполнена, клиент может получить ошибку с указанием ECONNREFUSED.

Accept:

Он извлекает первый запрос на соединение в очереди ожидающих соединений для прослушивающего сокета, sockfd, создает новый подключенный сокет и возвращает новый дескриптор файла, ссылающийся на этот сокет. В этот момент устанавливается соединение между клиентом и сервером, и они готовы к передаче данных.

Читать еще:  Язык программирования си что это

Этапы для клиента

  • Сокетное соединение: точно так же, как и при создании сокета сервера
  • Connect:

Системный вызов connect () соединяет сокет, указанный дескриптором файла sockfd, с адресом, указанным в addr. Адрес и порт сервера указаны в addr.

Реализация
Здесь мы обмениваемся одним приветственным сообщением между сервером и клиентом, чтобы продемонстрировать модель клиент / сервер.

// Серверная программа на C / C ++ для демонстрации программирования Socket
#include
#include
#include
#include
#include
#include
#define PORT 8080

int main( int argc, char const *argv[])

int server_fd, new_socket, valread;

struct sockaddr_in address;

int addrlen = sizeof (address);

char *hello = «Hello from server» ;

// Создание дескриптора файла сокета

if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)

perror ( «socket failed» );

// Принудительное подключение сокета к порту 8080

if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,

address.sin_port = htons( PORT );

// Принудительное подключение сокета к порту 8080

if (bind(server_fd, ( struct sockaddr *)&address,

perror ( «bind failed» );

if (listen(server_fd, 3)

if ((new_socket = accept(server_fd, ( struct sockaddr *)&address,

valread = read( new_socket , buffer, 1024);

printf ( «%sn» ,buffer );

send(new_socket , hello , strlen (hello) , 0 );

printf ( «Hello message sentn» );

// Клиентская программа C / C ++ для демонстрации программирования Socket
#include
#include
#include
#include
#include
#define PORT 8080

int main( int argc, char const *argv[])

int sock = 0, valread;

struct sockaddr_in serv_addr;

char *hello = «Hello from client» ;

if ((sock = socket(AF_INET, SOCK_STREAM, 0))

printf ( «n Socket creation error n» );

// Преобразование адресов IPv4 и IPv6 из текста в двоичную форму

if (inet_pton(AF_INET, «127.0.0.1» , &serv_addr.sin_addr)

printf ( «nInvalid address/ Address not supported n» );

if (connect(sock, ( struct sockaddr *)&serv_addr, sizeof (serv_addr))

printf ( «nConnection Failed n» );

send(sock , hello , strlen (hello) , 0 );

printf ( «Hello message sentn» );

valread = read( sock , buffer, 1024);

printf ( «%sn» ,buffer );

Компиляция:
gcc client.c -o клиент
gcc server.c -o сервер

Выход:

Next: Программирование на языке сокетов на C / C ++: обработка нескольких клиентов на сервере без многопоточности
Эта статья предоставлена Акшат Синха . Если вы как GeeksforGeeks и хотели бы внести свой вклад, вы также можете написать статью с помощью contribute.geeksforgeeks.org или по почте статьи contribute@geeksforgeeks.org. Смотрите свою статью, появляющуюся на главной странице GeeksforGeeks, и помогите другим вундеркиндам.

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

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

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

TCP/IP

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

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

OSI и TCP/IP

Порты

Полный список зарегистрированных портов расположен по адресу: 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, работающим с несколькими буферами:

Ссылка на основную публикацию
Adblock
detector