21.6.1 Вызовы в серверной программе TCP

21.6.1 Вызовы в серверной программе TCP

1. sockMain = socket (AF_INET, SOCK_STREAM, 0); Вызов socket имеет форму:

дескриптор_socket = socket(адрес_домена, тип_коммуникации, протокол)

Напомним, что интерфейс socket может использоваться для других видов коммуникаций, например XNS. AF_INET указывает на семейство адресов Интернета. SOCK_STREAM запрашивает socket TCP. Эта переменная должна иметь значение SOCK_DGRAM, чтобы создать socket UDP, a SOCK_RAW служит для непосредственного обращения к IP.

Не нужно явно определять никакую другую информацию протокола для TCP (или для UDP). Однако параметр protocol необходим для интерфейса с необработанными данными, а также для некоторых протоколов из других семейств, использующих socket.

2. struct sockaddr_in servAddr;

...

bzero((char *)&servAddr, sizeof(servAddr));

servAddr.sin_family = AF_INET;

servAddr.sin_addr.s_addr = htonl(INADDR_ANY);

servAddr.sin_port = 0;

Программная структура servAddr используется для хранения адресной информации сервера. Вызов bzero() инициализирует servAddr, помещая нули во все параметры. Первая переменная в структуре servAddr указывает, что остальная часть значений содержит данные семейства адресов Интернета.

Следующая переменная хранит локальный IP-адрес сервера. Например, если сервер подключен к локальной сети Ethernet и к сети X.25, может потребоваться ограничить доступ клиентов через интерфейс Ethernet. В данной программе об этом можно не беспокоится. INADDR_ANY означает, что клиенты могут соединяться через любой интерфейс.

Функция htonl() имеет полное название host-to-network-long. Она применяется для преобразования 32-разрядных целых чисел локального компьютера в формат Интернета для 32-разрядного адреса IP. Стандарты Интернета предполагают представление целых чисел с наиболее значимым байтом слева. Такой стиль именуется Big Endian (стиль "тупоконечников"). Некоторые компьютеры хранят данные, располагая слева менее значимые байты, т.е. в стиле Little Endian ("остроконечников"). Если локальный компьютер использует стиль Big Endian, htonl() не будет выполнять никакой работы.

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

3. bind(sockMain, &servAddr, sizeof(servAddr)); getsockname(sockMain, &servAddr, &length);

Вызов bind имеет форму:

возвращаемый_код = bind(дескриптор_socket, адресная_структура, длина_адресной_структуры)

Если адресная структура идентифицирует нужный порт, bind попытается получить его на сервере. Если переменная порта имеет значение 0, bind получит один из неиспользованных портов. Функция bind позволяет ввести номер порта и IP-адрес в TCB. Вызов getsockname имеет форму:

возвращаемый_код = getsockname(дескриптор_socket, адресная_структура, длина_адресной_структуры)

Мы запросили у bind выделение порта, но эта функция не сообщает нам, какой именно порт был предоставлен. Для выяснения этого нужно прочитать соответствующие данные из TCB. Функция getsockname() извлекает информацию из TCB и копирует ее в адресную структуру, где можно будет прочитать эти сведения. Номер порта извлекается и выводится следующим оператором:

printf("SERVER: Номер порта %d ", ntohs(servAddr.sin_port));

Функция ntohs() имеет полное название network-to-host-short и служит для преобразования номера порта из порядка следования байт в сети в локальный порядок следования байт на хосте.

4. listen(sockMain, 5);

Вызов listen применяется для ориентированных на соединение серверов и имеет форму:

возвращаемый_код = listen(дескриптор_socket, размер_очереди)

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

5. sockClient = accept(sockMain, 0, 0);

Вызов accept имеет форму:

новым_дескриптор_socket = accept(дескриптор_socket,

клиентская_адресная_структура, длина_клиентской_адресной_структуры)

По умолчанию вызов блокируется до соединения клиента с сервером. Если указана переменная клиентская_адресная_структура, после соединения клиента в эту структуру будут введены IP-адрес и порт клиента. В этом примере программы не проверяются IP-адрес и номер порта клиента, а просто два последних поля параметра заполняются нулями.

6. child = fork();

close(sockMain);

В языке С команда fork создает новый дочерний процесс, который наследует все дескрипторы ввода/вывода родительской программы, а также имеет доступ к sockMain и sockClient. Операционная система отслеживает количество процессов, имеющих доступ к socket.

Соединение закрывается, когда последний обращающийся к socket процесс вызывает close(). Когда дочерний процесс закрывает sockMain, родительский процесс все еще имеет доступ к socket.

7. close(sockClient);

Этот вызов выполняется из родительской части программы. Когда родительский процесс закрывает sockClient, дочерний процесс все еще имеет доступ к socket.

8. msgLength = recv(sockClient, buf, BUFLEN, 0));

close(sockClient);

Вызов recv имеет форму:

длина_сообщения = recv(дескриптор_socket, буфер, длина_буфера, флаги)

По умолчанию вызов recv блокированный. Функции fcntl() или iocntl() позволяют изменить статус socket на неблокированный режим.

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

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

Системные вызовы

Из книги Энциклопедия разработчика модулей ядра Linux автора Померанц Ори


Вызовы функций

Из книги Основы объектно-ориентированного программирования автора Мейер Бертран

Вызовы функций Вызовы функций имеют такой же синтаксис, как и вызовы процедур. Они могут быть квалифицированные и неквалифицированные: в первом случае используется нотация с многоточием. При соответствующих объявлениях класса и функций, они, например, таковы:b.fb.g(x, y,


Асинхронные вызовы процедур

Из книги Системное программирование в среде Windows автора Харт Джонсон М

Асинхронные вызовы процедур Основное возражение, которое можно предъявить к программе ThreeSage.c (программа 10.5) в ее нынешнем виде, касается прекращения выполнения передающего и принимающего потоков с помощью функции TerminateThread. В комментариях, включенных в код, вам


21.4 Вызовы socket

Из книги TCP/IP Архитектура, протоколы, реализация (включая IP версии 6 и IP Security) автора Фейт Сидни М

21.4 Вызовы socket Вызовы socket подготавливают сетевое взаимодействие путем создания блоков управления пересылкой (Transmission Control Block — TCB). В некоторых изданиях процесс создания TCB называется созданием socket. Вызов socket возвращает небольшое целое число, называемое дескриптором и


21.7.1 Вызовы в клиентской программе TCP

Из книги Разработка приложений в среде Linux. Второе издание автора Джонсон Майкл К.

21.7.1 Вызовы в клиентской программе TCP 1. sock = socket(AF_INET, SOCK_STREAM, 0);Клиент создает блок управления пересылкой ("socket") так же, как это делал сервер.2. Сервер должен инициализировать адресную структуру для использования в bind.Эта структура содержит локальный IP-адрес и номер порта


21.10.1 Вызовы в серверной программе UDP

Из книги Язык программирования Си для персонального компьютера автора Бочков C. О.

21.10.1 Вызовы в серверной программе UDP 1. sockMain = socket(AF_NET, SOCK_DGRAM, 0);Семейство адресов — снова Интернет.2. bzero((char *)&servAddr, sizeof(servAddr));servAddr.sin_family = AF_INET;servAddr.sin_addr.s_addr = htonl(INADDR_ANY);servAddr.sin_port = 0;Вызовы инициализации адресной структуры сервера те же, что и в программе для TCP.3. bind(sockMain,


9.2. Системные вызовы

Из книги Macromedia Flash Professional 8. Графика и анимация автора Дронов В. А.

9.2. Системные вызовы В этой книге практически повсеместно упоминаются системные вызовы, которые являются фундаментальными для программного окружения. На первый взгляд, они выглядят как обычные вызовы функций С. И это не случайно; они представляют собой специальную


Вызовы функций

Из книги Firebird РУКОВОДСТВО РАЗРАБОТЧИКА БАЗ ДАННЫХ автора Борри Хелен

Вызовы функций Синтаксис:<выражение> (<список-выражений>)Значением <выражения> должен быть адрес функции. В простейшем случае это идентификатор функции. <Список выражений> содержит выражения, разделенные запятыми. Значение каждого из этих выражений


Рекурсивные вызовы

Из книги Программирование для Linux. Профессиональный подход автора Митчелл Марк

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


Отправка данных серверной программе

Из книги Операционная система UNIX автора Робачевский Андрей М.

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


Получение данных от серверной программы

Из книги Разработка ядра Linux автора Лав Роберт

Получение данных от серверной программы Самый простой способ передать серверной программе данные и сразу же получить от нее результат их обработки — использовать действие loadVariabies или одноименный метод объекта movieClip. Это действие (метод) отправляет данные серверной


Вызовы функций

Из книги автора

Вызовы функций После установки Firebird содержит минимальный набор внутренних функций SQL. Хотя новые функции появляются время от времени, тем не менее сохраняется одно из основных достоинств Firebird: малый объем памяти, занимаемый сервером.Функциональные возможности сервера


5.5.2. Системные вызовы

Из книги автора

5.5.2. Системные вызовы Сокеты являются более гибкими в управлении, чем рассмотренные выше механизмы межзадачного взаимодействия. При работе с сокетами используются следующие функции:? socket() — создает сокет;? close() — уничтожает сокет;? connect() — устанавливает соединение


Отложенные вызовы

Из книги автора

Отложенные вызовы Отложенный вызов определяет функцию, вызов которой будет произведен ядром системы через некоторое время. Например, в SVR4 любая подсистема ядра может зарегистрировать отложенный вызов следующим образом:int co_ID = timeout(void (*fn)(), caddr_t arg, long delta);где fn() определяет


Глава 5 Системные вызовы

Из книги автора

Глава 5 Системные вызовы Ядро операционной системы предоставляет набор интерфейсов, благодаря которым процессы, работающие в пространстве пользователя, могут взаимодействовать с системой. Эти интерфейсы предоставляют пользовательским программам доступ к аппаратному


Вызовы syscall

Из книги автора

Вызовы syscall Системные вызовы (часто называемые syscall в ОС Linux) обычно реализуются в виде вызова функции. Для них могут быть определены один или более аргументов (inputs), которые могут приводить к тем или иным побочным эффектам[25], например к записи данных в файл или к