Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Калюжный. лабы.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
160.08 Кб
Скачать

Описание

Как только сокет создан и подключен, можно принимать из него данные вызовами recv() (для TCP SOCK_STREAM сокетов) и recvfrom() (для UDP SOCK_DGRAM сокетов).

Обе функции принимают дескриптор сокета s, указатель на буфер buf, длину буфера в байтах len, и набор флагов flags, определяющих работу функций.

Дополнительно, recvfrom() принимает struct sockaddr* from, указывающую откуда принимать данные и запишет в fromlen размер struct sockaddr. (Можно тоже инициализировать fromlen размером from или struct sockaddr.)

Возвращаемое значение

Возвращает число действительно принятых данных (что может быть меньше затребованного в параметре len), или -1 при ошибке (errno будет установлен соответственно.)

Если удалённая сторона закрыла соединение, то recv() вернёт 0. Это нормальный способ определения того, что удаленная сторона закрыла соединение.

Пример

/ потоковые сокеты и recv()

struct addrinfo hints, *res; int sockfd;

char buf[512]; int byte_count;

// получить информацию хоста, создать сокет и подключиться memset(&hints, 0, sizeof hints);

hints.ai_family = AF_UNSPEC; // использовать либо IPv4 либо IPv6 hints.ai_socktype = SOCK_STREAM; getaddrinfo("www.example.com", "3490", &hints, &res);

sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); connect(sockfd, res->ai_addr, res->ai_addrlen);

// Прекрасно! Мы подключены и можем принимать данные! byte_count = recv(sockfd, buf, sizeof buf, 0);

printf("recv()'d %d bytes of data in buf\n", byte_count);

//дейтаграммные сокеты и recvfrom()

struct addrinfo hints, *res; int sockfd;

int byte_count; socklen_t fromlen;

struct sockaddr_storage addr; char buf[512];

char ipstr[INET6_ADDRSTRLEN];

// получить информацию хоста, создать сокет и подключиться к порту 4950 memset(&hints, 0, sizeof hints);

hints.ai_family = AF_UNSPEC; // использовать либо IPv4 либо IPv6 hints.ai_socktype = SOCK_DGRAM;

hints.ai_flags = AI_PASSIVE; getaddrinfo(NULL, "4950", &hints, &res);

sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); bind(sockfd, res->ai_addr, res->ai_addrlen);

// accept() не нужен, только recvfrom(): fromlen = sizeof addr;

byte_count = recvfrom(sockfd, buf, sizeof buf, 0, &addr, &fromlen);

printf("recv()'d %d bytes of data in buf\n", byte_count); printf("from IP address %s\n",

inet_ntop(addr.ss_family,

addr.ss_family == AF_INET?

((struct sockadd_in *)&addr)->sin_addr:

((struct sockadd_in6 *)&addr)->sin6_addr,

ipstr, sizeof ipstr);

        1. select()

Проверяет готовы ли дескрипторы сокетов к чтению - записи.

Прототип

#include <sys/select.h>

int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,

struct timeval *timeout);

FD_SET(int fd, fd_set *set); FD_CLR(int fd, fd_set *set); FD_ISSET(int

fd,fd_set*set); FD_ZERO(fd_set *set);

Описание

Функция select() предоставляет способ одновременной проверки множества сокетов на предмет ожидания recv(), готовности к передаче данных через send() без блокирования или возникновения исключения.

После того как макросы вроде FD_SET() использованы массива структур можно передать его функции как один из следующих параметров: readfds если хотите знать, готов ли какой-нибудь сокет из массива к recv(), writefds если какой-либо сокет готов к send(), и/или exceptfds если если нужно узнать произошло ли на каком-нибудь исключение в сокете. Любой их этих параметров может быть NULL если этот тип событий неинтересен. После возврата из select() значения в массиве будут изменены, чтобы показать, какие сокеты готовы к чтению - записи и какие имеют исключения.

Первый параметр, n это наивысший номер дескриптора сокета (они просто int) плюс один.

Напоследок, struct timeval *timeout в конце позволяет указать select() как долго проверять эти массивы. Она вернёт управление при истечении таймаута или при возникновении события, смотря что раньше. В struct timeval есть два поля: tv_sec это количество секунд, к которому добавляется tv_usec, количество микросекунд

(1 000 000 микросекунд в секунде.) Вспомогательные макросы делают следующее: