Сокеты TCP предоставляют приложению поток байтов, лишенный маркеров записей. Возвращаемое значение функции read может быть меньше запрашиваемого, но это не обязательно является ошибкой. Чтобы упростить считывание и запись потока байтов, мы разработали три функции readn
, writen
и readline
, которые и используем в книге. Однако сетевые программы должны быть написаны в расчете на работу с буферами, а не со строками.
1. Почему аргументы типа «значение-результат», такие как длина структуры адреса сокета, должны передаваться по ссылке?
2. Почему и функция readn
, и функция writen
копируют указатель void*
в указатель char*
?
3. Функции inet_aton
и inet_addr
характеризуются традиционно нестрогим отношением к тому, что они принимают в качестве точечно-десятичной записи адреса IPv4: допускаются от одного до четырех десятичных чисел, разделенных точками; также допускается задавать шестнадцатеричное число с помощью начального 0x
или восьмеричное число с помощью начального 0 (выполните команду telnet 0xe
, чтобы увидеть поведение этих функций). Функция inet_pton
намного более строга в отношении адреса IPv4 и требует наличия именно четырех чисел, разделенных точками, каждое из которых является десятичным числом от 0 до 255. Функция inet_pton
не разрешает задавать точечно- десятичный формат записи адреса, если семейство адресов — AF_INET6
, хотя существует мнение, что это можно было бы разрешить, и тогда возвращаемое значение было бы адресом IPv4, преобразованным к виду IPv6 (см. рис. А.6). Напишите новую функцию inet_pton_loose
, реализующую такой сценарий: если используется семейство адресов AF_INET
и функция inet_pton
возвращает нуль, вызовите функцию inet_aton
и посмотрите, успешно ли она выполнится. Аналогично, если используется семейство адресов AF_INET6
и функция inet_pton
возвращает нуль, вызовите функцию inet_aton
, и если она выполнится успешно, возвратите адрес IPv4, преобразованный к виду IPv6.
Глава 4
Элементарные сокеты TCP
В этой главе описываются элементарные функции сокетов, необходимые для написания полностью работоспособного клиента и сервера TCP. Сначала мы опишем все элементарные функции сокетов, которые будем использовать, а затем в следующей главе создадим клиент и сервер. С этими приложениями мы будем работать на протяжении всей книги, постоянно их совершенствуя (см. табл. 1.3 и 1.4).
Мы также опишем параллельные (concurrent) серверы — типичную технологию Unix для обеспечения параллельной обработки множества клиентов одним сервером. Подключение очередного клиента заставляет сервер выполнить функцию fork
, порождающую новый серверный процесс для обслуживания этого клиента. Здесь применительно к использованию функции fork
мы будем рассматривать модель «каждому клиенту — один процесс », а в главе 26 при обсуждении программных потоков расскажем о модели «каждому клиенту — один поток ».
На рис. 4.1 представлен типичный сценарий взаимодействия, происходящего между клиентом и сервером. Сначала запускается сервер, затем, спустя некоторое время, запускается клиент, который соединяется с сервером. Предполагается, что клиент посылает серверу запрос, сервер этот запрос обрабатывает и посылает клиенту ответ. Так продолжается, пока клиентская сторона не закроет соединение, посылая при этом серверу признак конца файла. Затем сервер закрывает свой конец соединения и либо завершает работу, либо ждет подключения нового клиента.
Рис. 4.1. Функции сокетов для элементарного клиент-серверного соединения TCP
Чтобы обеспечить сетевой ввод-вывод, процесс должен начать работу с вызова функции socket
, задав тип желаемого протокола (TCP с использованием IPv4, UDP с использованием IPv6, доменный сокет Unix и т.д.).
#include
int socket(int family , int type , int protocol );
Возвращает: неотрицательный дескриптор, если функция выполнена успешно, -1 в случае ошибки
Константа family
задает семейство протоколов. Ее возможные значения приведены в табл. 4.1. Часто этот параметр функции socket
называют «областью» или «доменом» ( domain ), а не семейством. Значения константы type
(тип) перечислены в табл. 4.2. Аргумент protocol
должен быть установлен в соответствии с используемым протоколом (табл. 4.3) или должен быть равен нулю для выбора протокола, по умолчанию соответствующего заданному семейству и типу.
Читать дальше
Конец ознакомительного отрывка
Купить книгу