Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

СПО_1 / СПО / Sozdanie.setevyh.prilojenii.v.srede.Linux

.pdf
Скачиваний:
80
Добавлен:
11.04.2015
Размер:
2.94 Mб
Скачать

меняется, а файла получателя — меняется. Функция читает указанное число бай тов (параметр count) начиная с заданной позиции (параметр offset). По заверше нии функции указатель *offset ссылается на байт, идущий за последним прочи танным байтом.

Прототип

#include <unistd.h>

int sendfile(int out_fd, int in_fd, off_t *offset, size_t count);

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

При успешном завершении функция возвращает общее число скопированных байтов. В случае ошибки возвращается — 1, а в переменную errno записывается код ошибки.

Параметры

out_f

d

Дескриптор получателя (указатель текущей позиции файла меняется)

in_f

d

Дескриптор источника (указатель текущей позиции файла не меняется)

offset

Указатель на переменную, в которой содержится начальное смещение

count

Число отправляемых байтов

Возможные ошибки

EBADF

Входной файл не был открыт для чтения или выходной файл не был открыт

 

 

для записи

EINVAL

Дескриптор некорректен или заблокирован

ENOMEM

Недостаточно памяти для чтения из исходного файла

ЕЮ

 

Неопределенная ошибка при чтении из исходного файла

Пример

#include <unistd.h>

struct stat fdstat;

int client = accept(sd,0,0);

int fd = open("filename.gif", O_RDONLY); fstat(fd, &fdstat);

sendfile(client, fd, 0, fdstat.st_size); close(fd);

close(client);

recv()

Функция recv() принимает сообщение от подключенного однорангового ком пьютера, клиента или сервера. Она работает подобно низкоуровневой функции read(), но дополнительно позволяет устанавливать управляющие флаги.

Приложение Б. Сетевые функции

391

Ⱦɚɧɧɚɹ ɜɟɪɫɢɹ ɤɧɢɝɢ ɜɵɩɭɳɟɧɚ ɷɥɟɤɬɪɨɧɧɵɦ ɢɡɞɚɬɟɥɶɫɬɜɨɦ %RRNV VKRS Ɋɚɫɩɪɨɫɬɪɚɧɟɧɢɟ ɩɪɨɞɚɠɚ ɩɟɪɟɡɚɩɢɫɶ ɞɚɧɧɨɣ ɤɧɢɝɢ ɢɥɢ ɟɟ ɱɚɫɬɟɣ ɁȺɉɊȿɓȿɇɕ Ɉ ɜɫɟɯ ɧɚɪɭɲɟɧɢɹɯ ɩɪɨɫɶɛɚ ɫɨɨɛɳɚɬɶ ɩɨ ɚɞɪɟɫɭ piracy@books-shop.com

Прототип

#include <sys/socket.h> #include <resolv.h>

int recv(int sockfd, void *buf, int maxbuf, int options);

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

Функция возвращает число прочитанных байтов или 1 в случае ошибки.

Параметры

sockfd

Дескриптор подключенного сокета

buf

Буфер, в который будет помещено поступившее сообщение

maxbuf

Размер буфера

options

Набор флагов, которые можно объединять с помощью операции побитового сложения:

*MSG_OOB. Запрашивает получение внеполосных данных, которые не передаются в обычном пото

ке данных. В некоторых протоколах срочные данные помещаются в начало обычной очереди, по этому рассматриваемый флаг не может применяться при работе с такими протоколами;

*MSG_PEEK. Заставляет функцию читать данные, не удаляя их из очереди. Таким образом, при следующей операции чтения будут прочитаны те же самые данные;

*MSG_WAITALL. Запрашивает блокировку программы до тех пор, пока не будет получено все со

общение целиком. Тем не менее функция может завершиться досрочно, если получен сигнал, произошла ошибка или соединение было разорвано противоположной стороной;

*MSG_ERRQUEUE. Запрашивает прием пакета из очереди ошибок сокета. Информация об ошибке

передается в служебном сообщении, тип которого зависит от протокола (для IP сокета нужно ус тановить параметр IP_RECVERR). В теле сообщения находится структура sock_extended_error;

*MSG_NOSIGNAL. Отключает выдачу сигнала SIGPIPE в потоковом сокете при разрыве соединения на противоположной стороне

Возможные ошибки

EBADF

Указан неверный дескриптор файла

ENOTCONN

Сокет не был подключен (см. функции connect() и accept())

ENOTSOCK

Указанный дескриптор связан с файлом, а не с сокетом

EAGAIN

Задан режим неблокируемого ввода вывода, а данные недоступны, либо был установ

 

лен период тайм аута, который превышен до того, как были получены данные

EINTR

Сигнал прервал выполнение операции чтения, прежде чем данные стали доступны

EFAULT

Указатель буфера чтения ссылается за пределы адресного пространства процесса

EINVAL

Передан неверный аргумент

Пример

/*** Получение сообщения (TCP, UDP) от подключенного узла ***/

int sockfd;

int bytes, bytes_wrote=0;

/*— Создание сокета, подключение к серверу/узлу —*/ if ( (bytes = recv(sockfd, buffer, msg_len, 0)) < 0 )

392

Часть V. Приложения

www.books-shop.com

perror("send");

/*** Получение срочного сообщения (TCP) от подключенного узла ***/

/*** Этот код обычно находится в обработчике сигнала SIGURG ***/

int sockfd;

intbytes, bytes_wrote=0;

/*— Создание сокета, подключение к серверу —*/

if ( (bytes = recv(sockfd, buffer, msg_len, MSG_OOB)) < 0 ) perror("Urgent message");

recvfrom()

Функция recvfrom() принимает сообщение от неподключенного однорангового компьютера (UDP и неструктурированные сокеты). В протоколе Т/ТСР эта функция никогда не используется. Вместо нее вызывается функция accept().

Прототип

linclude <sys/socket.h> linclude <resolv.h>

int recvfromfint sockfd, void* buf, int buf_len, int options, struct sockaddr *addr, int *addr_len);

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

При успешном завершении возвращается число прочитанных байтов. В случае ошибки возвращается — 1, а в переменную errno записывается код ошибки.

Параметры

sockfd

Дескриптор сокета

buf

Буфер для приема сообщения

buf _lеп

Максимальный размер буфера (сообщение усекается, если буфер слишком мал)

options

Параметры управления каналом (такие же, как и в функции recv())

addr

Адрес и порт отправителя

addr_len

Максимальный размер адресной структуры (адрес усекается, если буфер слишком

 

 

мал); по завершении функции в этом параметре будет содержаться реальная длина

 

 

адреса

Возможные ошибки

(Те же, что и в функции recv())

Пример

struct sockaddr_in addr;

int addr_len=sizeof(addr), bytes_read; char buf[l024];

Приложение Б. Сетевые функции

393

www.books-shop.com

int

sockfd = socket (PF_INET, SOCK_DGRAM, 0);

/* —

привязка к конкретному порту —*/

bytes_read = recvfrom(sockfd, buf, sizeof(buf), 0, &addr,

 

&addr_len);

if(bytes_read<0)

 

perror("recvfrom failed");

recvmsg()

Функция recvmsg() принимает сразу несколько сообщений от одного источни ка. Она может использоваться с сокетами типа SOCK_DGRAM (аналогично тому, как это происходит в случае функции sendmsg()).

Прототип

#include <sys/socket.h> #include <resolv.h> #include <sys/uio.h>

int recvmsg(int sockfd, struct msghdr *msg, unsigned int options);

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

При успешном завершении возвращается общее число полученных байтов, в противномслучаевозвращается—1.

Параметры

sockfd

Дескриптор сокета

msg

Буфер для принимаемых данных

options

Параметры управления каналом (такие же, как и в функции recv( ))

Возможные ошибки

(Те же, что и в функции recv())

Пример

char buffer[MSGS][1000]; struct sockaddr_in addr; struct iovec io[MSGS]; struct msghdr msg;

bzero(&addr, sizeof(addr)); msg.msg_name = &addr; msg.msg_namelen = sizeof (addr); for ( i = 0; i < MSGS; i++ )

{

io[i].iov_base = buffer(i);

io[i].iov_len = sizeof (buffer[i]);

}

394

Часть V. Приложения

www.books-shop.com

msg.msg_iov = io; msg.msg_iovlen = MSGS;

if ( (bytes = recvmsg(sd, &msg, 0)) < 0 ) perror("recvmsg");

Разрыв соединения

После того как программа закончила сеанс связи с внешним узлом, она долж на закрыть соединение. Ниже описывается функция, ответственная за разрыв со единения.

shutdown()

Функция shutdown() закрывает указанные части канала передачи данных. Со единение, устанавливаемое посредством сокета, по умолчанию является двуна правленным. Если нужно сделать его доступным только для чтения или только для записи, то следует с помощью функции shutdown() закрыть один из концов канала.

Прототип

#include <sys/socket.h>

int shutdown(int sockfd, int how);

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

Если все прошло успешно, возвращается 0. В случае ошибки ее код можно найти в переменной еrrno.

Параметры

sockfd

Дескриптор сокета

how

флаг, указывающий на то, какую часть канала следует закрыть:

*SHUT_RD (0) — сделать канал доступным только для записи;

*SHUT _WR(1) — сделать канал доступным только для чтения;

*SHUT_RDWR (2) — закрыть обе половины канала (эквивалентно вызову функции close()). Выполнять эти действия можно только в отношении подключенных сокетов

Возможные ошибки

EBADF

Указан неверный дескриптор сокета

ENOTSOCK

Указанный дескриптор связан с файлом, а не с сокетом

ENOTCONN

Указанный сокет не является подключенным

Приложение Б. Сетевые функции

395

www.books-shop.com

Пример

int sockfd;

struct sockaddr_in addr;

sockfd = socket(PF_INET, SOCK_STREAM, 0); bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET;

addr.sin_port = htons(DEST_PORT); inet_aton (DEST_ADDR, &addr. sin_addr); connect(sockfd, &addr, sizeof(addr)); if ( shutdown(sockfd, SHUT_WR) != 0 )

PANIC("Can't make socket input only");

Преобразование данных в сети

Работая с данными по сети, необходимо учитывать порядок следования бай тов, преобразовывать адреса и т.д. В библиотеку Socket API входит достаточно большое число функций, помогающих получать информацию в нужном формате. Ниже описаны функции, которые использовались в книге.

htons(), htonl()

Функции htons() и htonl() преобразуют двоичные данные из серверного по рядка следования байтов в сетевой. В случае процессора с прямым порядком хра нения данных происходит перестановка байтов. Если в компьютере установлен процессор с обратным порядком байтов, функция возвращает свой аргумент в неизменном виде.

Прототип

#include

<netinet/in.h>

unsigned

short int htons(unsigned short int host_short);

unsigned

long int htonl(unsigned long int host_long);

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

Преобразованный аргумент (16 или 32 разрядный).

Параметры

host_short

16 разрядное значение с серверным порядком следования байтов

host_long

32 разрядное значение с серверным порядком следования байтов

Возможные ошибки

(отсутствуют)

396 Часть V. Приложения

www.books-shop.com

Пример

/*** Связываем сокет с портом 1023 ***/

struct sockaddr_in addr; addr.sin_port = htons(1023);

/*** Связываем сокет с адресом 128.1.32.10 ***/

struct sockaddr_in addr; addr.sin_addr.s_addr = htonl(Ox8001200A);

ntohs(), ntohl()

Функции ntohs() и ntohl() преобразуют двоичные данные из сетевого порядка следования байтов в серверный.

Прототип

#include <netinet/in.h>

unsigned short int ntohs(unsigned short int network_short); unsigned long int ntohl(unsigned long int network_long);

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

Преобразованный аргумент (16 или 32 разрядный).

Параметры

 

network_short

16 разрядное значение с сетевым порядком следования байтов

network_long

32 разрядное значение с сетевым порядком следования байтов

Возможные ошибки

(отсутствуют)

Пример

struct sockaddr_in addr;

int client, addrlen=sizeof(addr);

client = accept(sockfd, &addr, &addrlen); if ( client > 0 )

printf("Connected %lX:%d\n", ntohl(addr.sin_addr), ntohs(addr.sin_port));

inet_addr()

Функция inet_addr() считается устаревшей. Она преобразует IP адрес из то чечной нотации в двоичную форму с сетевым порядком следования байтов. В случае неудачи возвращается значение — 1, которое также является корректным IP адресом (255.255.255.255). Лучше пользоваться функцией inet_aton().

Приложение Б. Сетевые функции

397

www.books-shop.com

Прототип

#include<netinet/in.h>

unsigned long int inet_addr(const char *ip_address);

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

He нуль

Если все прошло успешно, возвращается преобразованный IP адрес

INADDR_NONE ( 1)

Аргумент является неправильным. (Это ошибка функции. Она не возвращает от

 

рицательное значение, а значение 255.255.255.255 обозначает обычный ши

 

роковещательный адрес.)

Параметры

 

ip_address

IP адрес в традиционной, точечной нотации (например, 128.187.34.2)

Возможные ошибки

(переменная errno не устанавливается)

Пример

if ( (addr.sin_addr.s_addr = inet_addr("182.187.34.2")) == 1 ) perror("Couldn't convert address");

inet_aton()

Функция inet_aton() преобразует IP адрес из точечной нотации в двоичную форму с сетевым порядком следования байтов. Она заменяет функцию inet_addr().

Прототип

#include <netinet/in.h>

int inet_aton(const char *ip_addr, struct in_addr *addr);

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

Если все прошло успешно, возвращается ненулевое значение. В противном случае возвращается нуль.

Параметры

 

ip_addr

ASCII строка с IP адресом (например, 187.34.2.1)

addr

Переменная, куда записывается адрес; обычно заполняется поле sin_addr

 

структуры sockaddr_in

398 Часть V. Приложения

www.books-shop.com

Возможные ошибки

(переменная errno не устанавливается)

Пример

struct sockaddr_in addr;

if ( inet_aton("187.43.32.1", &addr.sin_addr) == 0 perror("inet_aton() failed");

inet_ntoa()

Функция inet_ntoa() преобразует IP адрес из двоичной формы с сетевым по рядком следования байтов в точечную нотацию.

Прототип

iinclude <netinet/in.h>

int inet_ntoa(struct in_addr *addr);

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

Функция возвращает строку с адресом.

Параметры

 

addr

Двоичный адрес (обычно это адресное поле структуры sockaddr_in)

Возможные ошибки

(переменная errno не устанавливается)

Пример

 

clientfd = accept(serverfd, &addr, &addr_size);

if ( clientfd > 0 )

printf("Connected %s:%d\n", inet_ntoa(addr.sin_addr),

 

ntohs(addr.sin_port));

inet_pton()

Функция inet_pton() преобразует адрес IPv4 или IPv6 из символьного пред ставления в двоичную форму с сетевым порядком следования байтов.

Прототип

Iinclude <arpa/inet.h>

int inet_pton(int domain, const char* prsnt, void* addr);

Приложение Б. Сетевые функции

399

www.books-shop.com

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

В случае успешного завершения возвращается ненулевое значение. Если воз никает ошибка, возвращается нуль.

Параметры

domain

Семейство адресов (AF_INET или AF_INET6)

 

prsnt

ASCII строка с IP адресом (например, 187.34.2.1 или

FFFF:8090:АОЗ:3245)

addr

Переменная, куда записывается адрес; обычно заполняется поле sin_addr структуры

 

sockaddr_in или поле sin6_addr структуры sockaddr_in6

Возможные ошибки

(переменная errno не устанавливается)

Пример

struct sockaddr_in addr;

if ( inet_pton(AF_INET, "187.43.32.1", &addr.sin_addr) == 0 ) perror("inet pton() failed");

inet_ntop()

Функция inet_pton() преобразует адрес из двоичного представления с сетевым порядком следования байтов в символьную форму. Функция поддерживает се мейства адресов AF_INET и AF_INET6.

Прототип

#include <arpa/inet.h>

int inet_ntop(int domain, struct in_addr *addr, char* str, int len);

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

Функция возвращает строку str.

Параметры

domain

Семейство адресов (AF_INET или AF_INET6)

addr

Двоичный адрес (обычно это адресное поле структуры sockaddr in)

str

Буфер для строки адреса

len

Размер буфера

400

Часть V. Приложения

www.books-shop.com

Соседние файлы в папке СПО
  • #
    11.04.201527.19 Mб69Cpp4Unix.pdf
  • #
    11.04.201516.44 Mб52IP Arhitektura, protokoly, realizatsiya (vklyuchaya IP versii s IP Security).djvu
  • #
  • #
    11.04.201510.72 Mб51Стивенс. UNIX. Разработка сетевых приложений.djvu