TCP/IP Архитектура, протоколы, реализация (включая IP версии 6 и IP Security)
Шрифт:
21.6.1 Вызовы в серверной программе TCP
1. sockMain = socket (AF_INET, SOCK_STREAM, 0); Вызов 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
Если сервер взаимодействует через общеизвестный порт, номер этого порта нужно записать в следующую переменную. Поскольку мы хотим, чтобы операционная система сама присвоила порт для нашей тестовой программы, мы вводим нулевое значение.
3. bind(sockMain, &servAddr, sizeof(servAddr)); getsockname(sockMain, &servAddr, &length);
Вызов bind имеет форму:
Если адресная структура идентифицирует нужный порт, bind попытается получить его на сервере. Если переменная порта имеет значение 0, bind получит один из неиспользованных портов. Функция bind позволяет ввести номер порта и IP-адрес в TCB. Вызов getsockname имеет форму:
Мы запросили у bind выделение порта, но эта функция не сообщает нам, какой именно порт был предоставлен. Для выяснения этого нужно прочитать соответствующие данные из TCB. Функция getsockname извлекает информацию из TCB и копирует ее в адресную структуру, где можно будет прочитать эти сведения. Номер порта извлекается и выводится следующим оператором:
Функция ntohs имеет полное название network-to-host-short и служит для преобразования номера порта из порядка следования байт в сети в локальный порядок следования байт на хосте.
4. listen(sockMain, 5);
Вызов listen применяется для ориентированных на соединение серверов и имеет форму:
Вызов listen указывает, что это будет пассивный socket, и создает очередь требуемого размера для хранения поступающих запросов на соединения.
5. sockClient = accept(sockMain, 0, 0);
Вызов accept имеет форму:
По умолчанию вызов блокируется до соединения клиента с сервером. Если указана переменная клиентская_адресная_структура, после соединения клиента в эту структуру будут введены IP-адрес и порт клиента. В этом примере программы не проверяются IP-адрес и номер порта клиента, а просто два последних поля параметра заполняются нулями.