Читаем Linux: Полное руководство полностью

Последний параметр — это размер структуры 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()

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

#include

#include

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() возвращает отрицательное значение.

<p>27.3.4. Функция gethostbyname()</p>

Пользователям обычно удобнее указать символьное имя сервера, чем его IP-адрес. Для разрешения имени служит функция gethostbyname(). Вот ее прототип:

#include

#include

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`\n", *argv);

 exit(1);

}

// Выводим IP-адрес. Вывод в виде: имя -> адрес

printf("%s -> %s \n", *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;

Ей нужно передать три параметра — дескриптор сокета, адрес структуры, которая будет содержать информацию о нашем узле (его адрес). Третий параметр будет содержать длину адресной структуры.

<p>27.3.5. Функции сетевого ввода/вывода</p>

После успешного установления соединения можно начать обмен данными. Для отправки и получения данных можно использовать обыкновенные функции для работы с файлами — read() и write(), только вместо дескриптора файла нужно указывать дескриптор сокета. Однако рекомендуется использовать системные вызовы send() и recv(), которые предназначены именно для работы с сокетами. Эти системные вызовы будут рассмотрены ниже.

Если вы работаете в режиме без установления соединения, вам нужно использовать функции sendto() и recvfrom(). Первая функция отправляет данные, а вторая — принимает. Функция sendto() вместе с данными позволяет указать адрес получателя, a recvfrom() возвращает не только полученные данные, но и адрес отправителя.

Перейти на страницу:

Все книги серии Полное руководство

Похожие книги