
-
Привязка сокета (bind())
Данный вызов позволяет связать локальный адрес с сокет-дескриптором, создаваемым socket (). Эта операция является необязательной для клиентов, использующих сокет с установлением логического (виртуального) соединения, так как адрес присваивается в момент соединения с сервером в случае, если связыва-ние не произошло. Для сокетов в режиме дейтаграмм, эта операция является необходимой только в случае, если процесс должен получить данные. Для сокетов TCP/IP возможно присвоение номеру порта нулевого значения. Система присваивает номер, который можно получить посредством примитива getsockname ().
int bind (sock, localaddr, addrlen)
int sock - дескриптор сокета struct sockaddr *localaddr - локальный сокет-адрес int addrlen - длина адреса
-
Соединение клиента c сервером (connect())
int connect (sock, servaddr, addrlen)
int sock; - сокет-дескриптор struct sockaddr *servaddr; -адрес сервера int addrlen; - длина адреса
-
установка сервера в режим "прослушивания" (listen())
Этот примитив указывает, что сервер готов к получению запросов на соединение. Параметр qlen указывает на максимальное число запросов, которое может быть установлено в режим ожидания обработки.
int listen (sock, qlen)
int sock; - сокет-дескриптор int qlen; - макс. число необработ. подсоединений
-
Согласие сервера на соединение (accept())
Этот вызов используется сервером для ожидания запросов клиентов. Два последних параметра могут быть установлены в 0, кроме случаев, когда необходимо проверить идентичность клиента. Благодаря этому примитиву сервер дает клиенту понять, что его запрос принят. Примитив accept () возвращает новый сокет-дескриптор, который будет использован для обмена данными с клиентом. Для сервера имеется возможность создания порожденного процесса, который воспользуется вновь созданным дескриптором, в то время как порождающий процесс вновь перейдет в состояние ожидания соединения (accept ()) на сокете, открытом функцией socket ().
int accept (sock, addrdistant, addrlen)
int sock; - сокет-дескриптор struct sockaddr *addrdistant; - адрес телекоммуник. int *addrlen; - длина адреса
6.Примитивы считывания и записи read(), write(), send(), recv(), sendto(), recvfrom() Вызовы read () и write () используются также, как и для дескриптора файла. Вызовы send () и recv () имеют дополнительный аргумент, позволяющий, кроме всего прочего, посылать экспресс-данные. Вызовы send to () и recv from () используются для сокетов типа SOCK_DGRAM. Два дополнительных параметра позволяют уточ-нить адрес удаленного компьютера в случае sendto() и восстановить этот адрес в случае recvfrom().
7. Закрытие соединения
int close (sock)
int sock; - сокет-дескриптор
Перед закрытием ядро пытается переслать еще не посланные данные.
В листинге 1 приведен код сервера, использующего поточные сокеты (на языке Си).
Листинг 1 - Пример кода сервера на языке Си
/* Код сервера на языке Си */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define port 1100
int main(void) {
struct sockaddr_in stSockAddr;/*структура для хранения адресной
информации*/
/*1.создаем «слушающий» сокет*/
int listenSocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listenSocketFD == -1) {
perror("ошибка при создании сокета");
exit(EXIT_FAILURE);
}
/*обнуляем и заполняем структуру с адресной информацией */
memset(&stSockAddr, 0, sizeof (stSockAddr));
stSockAddr.sin_family = PF_INET;
stSockAddr.sin_port = htons(port);
stSockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
/*2. Привязываем сокет к адресу*/
if (bind(listenSocketFD, (struct sockaddr*) &stSockAddr, sizeof (stSockAddr)) == -1) {
perror("Ошибка: связывания");
close(i32SocketFD);
exit(EXIT_FAILURE);
}
/*3. Переводим «слушающий» сокет в режим прослушивания сети*/
if (listen(listenSocketFD, 10) == -1) {
perror("Ошибка: прослушивания");
close(listenSocketFD);
exit(EXIT_FAILURE);
}
/*в бесконеном цикле создаем новое подключение и осуществляем взаимодействия с подключенными клиентами (Последовательно)*/
for (;;) {
/*4. Как только клиент попытается подключится к серверу функция accept() вернет дескриптор «рабочего» сокета, по которому будет осуществляться взаимодействие*/
int workConnectSocketFD = accept(listenSocketFD, 0, 0);
if (workConnectSocketFD < 0) {
perror("Ошибка: принятия подключения клиента");
close(listenSocketFD);
exit(EXIT_FAILURE);
}
/* выполнение операций чтения и записи при помощи
созданного рабочего сокета*/
shutdown(workConnectSocketFD, SHUT_RDWR);
/*Закрываем сокет*/
close(workConnectSocketFD);
}
return 0;
}