запроса на соединение от клиента. Прототип этой функции следующий:
#include <sys/socket.h>
extern int listen (int __fd, int __n) __THROW;
Первый параметр — это дескриптор сокета, а второй — максимальное количество запросов на установление связи (другими словами, максимальное количество клиентов).
Как и функция bind(), функция listen() в случае успеха возвращает 0. Пример вызова функции:
if (listen (sock1, 3) != 0) {
printf('Ошибка при вызове listen(sock1, 3)
');
exit(1);
}
Используется программой-клиентом для отправки запроса на подключение к серверу. Прототип функции следующий:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
extern int connect (int __fd, struct sockaddr_in *addr,
socklen_t __len) __THROW;
Первый параметр — это дескриптор сокета, созданного функцией socket() и привязанного функцией bind(). Привязку сокета функцией bind() выполнять не обязательно: если сокет не был привязан до вызова connect(), привязка будет выполнена автоматически.
Второй параметр — это указатель на структуру типа sockaddr_in, содержащую информацию о сервере: его IP-адрес, номер порта, а также семейство протоколов.
Последний параметр — это размер структуры sockaddr_in в байтах. В случае успеха функция возвращает 0, а в случае ошибки —1.
Вот пример использования вызова connect:
struct sockaddr_in server;
struct hostent *h;
...
// определяем IP-адрес сервера
h = gethostbyname('server.domain.ru');
memcpy((char*)&server.sin_addr, h->h_addr, h->h_length);
// Определяем порт сервера
server.sin_port = 1234;
// Определяем семейство протоколов
server.sin_family = AF_INET;
// Вызов функции connect()
connect(sock, &server, sizeof(server));
Если вы используете режим без установления соединения (SOCK_DGRAM), вызов connect () необязателен.
Если максимальное число клиентов не превышено, сервер может принять запрос клиента. Для этого используется функция accept(). Данная функция используется только при работе в режиме с установлением соединения. Прототип функции следующий:
#include <sys/socket.h>
#include <netinet/in.h>
extern int accept(int __fd, struct sockaddr_in *addr,
socklen_t *__restrict __len) __THROW;
Первый параметр — это дескриптор сокета, второй — указатель на структуру, где можно разместить адрес клиента, причем данную структуру инициализировать не нужно. Последний параметр — размер структуры, указанной во втором параметре.
Системный вызов accept() работает так. Сначала он извлекает из очереди listen() запрос на соединение и создает новый сокет, через который будет производиться обмен данными с клиентом, например:
// получаем сокет клиента
sock2 = accept(sock1, &client, &ans_len);
// передаем клиенту информацию
write(sock2, MSG_TO_SEND, sizeof(MSG_TO_SEND));
Если вызов accept() завершился успехом, структура addr, задаваемая во втором параметре, будет содержать IP-адрес клиента.
Если очередь listen() пуста, то наш сервер будет ожидать появления нового клиента. В случае ошибки функция accept() возвращает отрицательное значение.
27.3.4. Функция gethostbyname()
Пользователям обычно удобнее указать символьное имя сервера, чем его IP-адрес. Для разрешения имени служит функция gethostbyname(). Вот ее прототип:
#include <netinet/in.h>
#include <netdb.h>
struct hostent *gethostbyname(char *name);
Данная функция возвращает указатель на структуру типа hostent, содержащую следующие поля:
♦ char *h_name — доменное имя узла;
♦ char **h_aliases — псевдонимы узла, если таковые определены;
♦ char *h_addr — IP-адрес узла;
♦ int h_addrtype — набор используемых протоколов (в нашем случае — AF_INET);
♦ int h_length — длина адреса узла.
Примеры использования функции:
struct hostent *h;
h = gethostbyname(*argv);
if (h==NULL) {
printf('Невозможно разрешить имя: `%s`
', *argv);
exit(1);
}
// Выводим IP-адрес. Вывод в виде: имя -> адрес
printf('%s -> %s
', *argv,
inet_ntoa(*((struct in_addr *)h->h_addr_list[0])));
Узнать свой собственный адрес можно с помощью функции getsockname():
extern int getsockname(int __fd, __SOCKADDR_ARG __addr,
socklen_t *__restrict __len) __THROW;
Ей нужно передать три параметра — дескриптор сокета, адрес структуры, которая будет содержать