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

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

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

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

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

Пример

char str[100];

clientfd = accept(serverfd, &addr, &addr_size); if ( clientfd > 0 )

printf("Connected %s:%d\n",

inet_ntop(AF_INET, addr.sin_addr, str, sizeof(str)), ntohs(addr.sin_port));

Работа с сетевыми адресами

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

getpeername()

Функция getpeername() определяет адрес или имя компьютера, подключенного к противоположному концу сокета с дескриптором sockfd. Результат помещается в буфер addr. Параметр addr_len определяет размер адресного буфера. Это та же самая информация, которую можно получить с помощью функции accept().

Прототип

#include <sys/socket.h>

int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addr_len);

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

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

еекод помещается в переменную errno.

Параметры

sockfd

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

 

addr

Буфер, в который помещается адресная структура

 

addr_len

Размер буфера; этот параметр передается по ссылке, так как функция записывает

 

сюда реальный размер адреса

 

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

 

EBADF

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

 

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

401

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

ENOTSOCK

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

ЕNOТСОNN

Сокет не подключен

ENOBUFS

В системе недостаточно ресурсов для выполнения операции

EFAULT

Указатель addr ссылается за пределы адресного пространства процесса

Пример

struct sockaddr_in addr; int addr_len = sizeof(addr);

if { getpeername(client, &addr, &addr_len) != 0 ) perror("getpeername() failed");

printf("Peer: %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));

gethostname()

Функция gethostname() возвращает имя локального узла. Результат помещается в буфер name, размер которого определяется параметром len.

Прототип

#include <unistd.h>

int gethostname(char *name, size_t len);

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

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

еекод помещается в переменную errno.

Параметры

name

Буфер, в который записывается имя узла

len

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

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

EINVAL

Параметр len является отрицательным либо, если функция выполняется на платформе

 

Linux/i386,значение параметра len оказалось меньше, чем реальный размер имени

EFAULT

Параметр name содержит неправильный адрес

Пример

char name[50];

if ( gethostname(name, sizeof(name)) != 0 perror("gethostname() failed");

printf("My host is: %s\n", name);

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

www.books-shop.com

gethostbyname()

Функция gethostbyname() ищет имя узла в базе данных DNS сервера и преоб разует его в IP адрес. Функции может передаваться как имя, так и сам адрес. Во втором случае поиск не осуществляется; вместо этого адрес возвращается в полях h name и h addr list[0] структуры hostent.

Прототип

#include <netdb.h>

struct hostent *gethostbyname(const char *name);

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

Функция возвращает указатель на структуру hostent. В случае неудачи возвра щается NULL. В структуре содержится список всех имен и адресов, связанных с данным узлом. Макроконстанта h_addr существует для совместимости со старыми приложениями.

#define h_addr h_addr_list[0]

 

 

struct hostent {

 

 

 

 

 

char

*h_name;

 

/* официальное имя узла */

 

char

**h_aliases;

/* список псевдонимов */

 

int

h_addrtype;

/* тип адреса */

 

int

h_length;

 

/*

длина

адреса */

 

char **h_addr_list;

/*

список

адресов; нулевой главный

*/

};

 

 

 

 

 

 

Параметры

 

 

 

 

 

name

 

 

Имя узла для поиска или IP адрес

 

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

 

 

ENOTFOUND

 

Указанный узел не найден

 

NO_ADDRESS, NO_DATA

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

NO_RECOVERY

 

Произошла фатальная ошибка сервера имен

 

EAGAIN

 

 

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

Пример

 

 

 

 

 

int i;

 

 

 

 

 

 

struct hostent *host;

 

 

 

 

host = gethostbyname("sunsite.unc.edu");

 

if ( host

!= NULL

)

 

 

 

 

{

 

 

 

 

 

 

printf("Official name: %s\n", host >h_name);

 

for ( i = 0; host >h_aliases[i] != 0; i++)

 

 

printf("

alias[%d]: %s\n", i+1, host >h_aliases[i]);

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

403

www.books-shop.com

printf("Address type=%d\n", host >h_addrtype); for ( i = 0; i < host >h_length; i++)

printf("Addr[%d]: %s\n", i+1, inet_ntoa(host >h_addr_list[i]));

}

else

perror("sunsite.unc.edu");

getprotobyname()

Функция getprotobyname() просматривает файл /etc/protocols в поиске прото кола с указанным именем. Эту функцию можно использовать для трансляции имен протоколов, таких как HTTP, FTP или Telnet, в соответствующие им номе ра портов.

Прототип

#include<netdb.h>

struct protoent *getprotobyname(const char* pname);

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

В случае успешного завершения функция возвращает указатель на структуру protoent. В противном случае возвращается NULL.

struct protoent {

 

char

*p_name;

/* официальное имя протокола */

char

**p_aliases; /* список псевдонимов */

int

p_proto;

/* номер порта */

};

Параметры

pname Имя протокола; это может быть любое известное имя протокола или псевдоним

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

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

Пример

#include <netdb.h>

int i;

struct protoent *proto = getprotobyname("http"); if ( proto != NULL )

{

printf("Official name: %s\n", proto >name); printf("Port!: %d\n", proto >p proto);

for ( i = 0; proto >p aliases[I] != 0;

404

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

www.books-shop.com

printf("Alias[%d]: %s\n", i+1, proto >p_aliases[i]);

else perror("http");

Управление сокетами

Когда сокет открыт, можно менять самые разные его параметры. Для этой це ли предназначены описанные ниже функции.

setsockopt()

Функция setsockopt() изменяет поведение сокета. У каждого параметра сокета есть значение (некоторые доступны только для чтения). Полный список парамет ров приведен в приложении А, "Информационные таблицы".

Прототип

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

int setsockopt(int sd, int level, int optname,

const void *optval, socklen_t optlen);

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

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

еекод помещается в переменную errno.

Параметры

 

 

sd

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

 

level

Уровень параметра сокета (SOL_SOCKET, SOL_IP, SOL_IPV6, SOL_TCP)

 

optname

Имя параметра сокета

 

optval

Указатель на новое значение параметра сокета

 

optlen

Длина параметра сокета в байтах

 

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

 

EBADF

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

 

ENOTSOCK

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

 

ENOPROTOOPT

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

 

EFAULT

Указатель optval ссылается за пределы адресного пространства процесса

 

Примеры

 

 

const int TTL=128;

 

/*— Задание предельного числа переходов равным 128 —*/

 

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

405

www.books-shop.com

if ( setsockopt(sd, SOL_IP, SO_TTL, &TTL, sizeof(TTL)) != 0 ) perror("setsockopt() failed");

getsockopt()

Функция getsockopt() возвращает значение указанного параметра сокета.

Прототип

#include <sys/types.h> iinclude <sys/socket.h>

int getsockopt(int sd, int level, int optname, void *optval, socklen_t *optlen);

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

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

еекод помещается в переменную errno.

Параметры

sd

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

level

Уровень параметра сокета (SOL_SOCKET, SOL_IP, SOL_IPV6, SOL_TCP)

optname

Имя параметра сокета

optval

Буфер для значения параметра сокета

optlen

Длина буфера; это значение передается по ссылке, так как функция записывает

 

сюда реальную длину буфера

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

EBADF

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

ENOTSOCK

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

ENOPROTOOPT

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

EFAULT

Указатель optval или optlen ссылается за пределы адресного пространства

 

процесса

Пример

int error, size = sizeof(error);

if ( getsockopt(sd, SOL_SOCKET, SO_ERROR, &error, &size)) != 0 ) perror("getsockopt() failed");

printf("socket error=%d\n", error);

406

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

www.books-shop.com

API функции ядра

Приложение

 

В

В этом приложении...

 

Задания

408

Потоки

415

Блокировка

418

Сигналы

421

Работа с файлами

424

www.books-shop.com

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

Задания

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

fork()

Функция fork() создает новый процесс (независимое задание). Дочерний про цесс выполняет тот же программный файл, что и его предок. Необходимо преду смотреть ветвление алгоритма в программе, иначе произойдет дублирование ис полняемого кода.

Прототип

#include <unistd.h> pid_t fork(void);

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

0 Текущее задание является дочерним >0 Текущее задание является родительским

<0 Дочернее задание не удалось создать; код ошибки содержится в переменной errno

Параметры

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

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

EAGAIN

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

 

информационной структуры дочернего задания

ENOMEM

Недостаточно памяти для создания необходимых структур ядра

Пример

int PID;

if ( (PID = fork()) == 0 )

{/*— ПОТОМОК —*/

/*** выполняем соответствующие действия ***/

exit(status);

}

else if ( PID > 0 )

{/*— ПРЕДОК —*/

408

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

www.books-shop.com

int status;

/*** выполняем соответствующие действия ***/

wait(Sstatus); /* эта функция может вызываться

в обработчике сигнала SIGCHLD */

}

else /*— ОШИБКА —*/ perror("fork() failed");

_clone()

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

Прототип

iinclude <sched.h>

int _clone(int (*fn)(void* arg), void* stacktop, int flags, void* arg);

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

Функция возвращает идентификатор созданного задания. В случае неудачи код ошибки записывается в переменную errno.

Параметры

f n

Указатель на функцию потока, принимающую аргумент типа void*; когда она завер

 

шается, операционная система останавливает поток

stacktop

Указатель на вершину стека дочернего задания (самый старший адрес блока данных);

 

этот стек имеет фиксированный размер и не может увеличиваться подобно стеку

 

обычного задания

flags

Набор флагов, определяющих, какие области памяти совместно используются и какой

 

сигнал посылать в случае завершения дочернего задания. Поддерживаются все виды

 

сигналов, и при завершении задания операционная система сгенерирует любой ука

 

занныйсигнал.

 

Следующие флаги определяют, какие из областей памяти задания будут доступны для

 

совместного использования:

*CLONE_VM. Совместное использование области данных между заданиями. Если флаг указан,

будут доступны все статические и предварительно инициализированные переменные, а так же блоки, выделенные в куче. В противном случае в дочернем задании будет создана копия области данных;

*CLONE_FS. Совместное использование информации о файловой системе: о текущем катало ге, корневом каталоге и стандартном режиме доступа к файлам (значение umask). Если флаг не указан, задания будут вести себя независимо друг от друга;

*CLONE FILES. Совместное использование открытых файлов. Когда в одном задании пере мещается указатель текущей позиции файла, в другом задании отразится это изменение, и если закрыть файл в одном задании, то и в другом он станет недоступным. Если флаг не

Приложение В. API функции ядра

409

www.books-shop.com

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

*CLONE SIGHAND. Совместное использование таблиц сигналов. Каждое задание может запре тить обработку того или иного сигнала с помощью функции sigprocmask( ) , и это не отра зится на других заданиях. Если флаг не указан, в дочернем задании создается копия табли цы сигналов;

*CLONE_PID.Совместное использование идентификатора процесса. Применятьданный флаг

следует осторожно, так как он не всегда поддерживается (как это имеет место в случае биб лиотеки Pthreads). Если флаг не указан, в дочернем задании создается новый идентификатор процесса

arg

Указатель на блок данных, передаваемых в качестве параметра потоковой функции fп.

 

Эти данные должны находиться в совместно используемой области памяти

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

EAGAIN

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

 

дания информационной структуры дочернего задания

ENOMEM

Недостаточно памяти для создания необходимых структур ядра

Пример

fdefine STACKSIZE 1024

void Child(void *arg)

{

/* код потомка */

exit(O);

}

int main (void)

{int cchild;

char *stack = malloc( STACKSIZE);

if ( (cchild = _clone(&Child, stack+STACKSIZE 1,

SIGCHLD, 0)) == 0 )

{ /*** секция дочернего задания — недоступна ***/

}

else if ( cchild > 0 ) wait();

else

perror("Can't clone task");

}

exec()

Функции данного семейства предназначены для запуска внешних программ (это могут быть либо двоичные исполняемые файлы, либо сценарии, начинающиеся со строки вида #! <интерпретатор> [аргументы]). Функция замещает контекст те кущего выполняемого задания контекстом внешней программы, которая сохраняет идентификатор запустившего ее процесса и список открытых файлов.

410

Часть 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