Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учеб.пос.СП.doc
Скачиваний:
28
Добавлен:
31.03.2015
Размер:
1.33 Mб
Скачать
    1. Основные системные вызовы для работы с сокетами, образующими логические соединения

Рассмотрим пять основных вызовов, начиная с вызова socket:

socket – создает объект для организации сетевых взаимодействий

#include <sys/socket.h>

int socket (

int domain, /* домен адреса (AF_UNIX, AF_INET) */

int type, /* SOCK_STREAM, SOCK_DGRAM */

int protocol /* детализирует аргумент type (обычно – ноль) */

);

/* Возвращает файловый дескриптор или -1 в случае ошибки (код ошибки - в errno) */

Файловый дескриптор, возвращаемый вызовом socket, может использоваться в следующих целях:

  • сервером - для приема входящих соединений системным вызовом accept;

  • клиентом – для выполнения операций ввода-вывода после того, как соединение будет установлено вызовом connect.

После создания сокета сервер должен присвоить ему адрес системным вызовом bind:

bind - присваивает адрес сокету

#include <sys/socket.h>

int bind (

int socket_fd, /* файловый дескриптор сокета */

const struct sockaddr *sa, /* адрес сокета */

socklen_t sa_len /* длина адреса */

);

/* Возвращает 0 в случае успеха или -1 в случае ошибки (код ошибки - в errno) */

В большинстве систем для адресов из домена AF_UNIX системный вызов bind создает новый файл сокета - он не может повторно использовать существующий файл. Чтобы подготовить сокет к приему входящих соединений, сервер должен обратиться к вызову listen:

listen - подготавливает сокет к приему запросов на соединение и устанавливает ограничение на размер очереди запросов

#include <sys/socket.h>

int listen (

int socket_fd, /* файловый дескриптор сокета */

int backlog /* максимальное число запросов на соединение в очереди */

);

/* Возвращает 0 в случае успеха или -1 в случае ошибки (код ошибки - в errno) */

Запросы на соединение помещаются в очередь, где дожидаются обработки. Второй аргумент backlog ограничивает размер этой очереди. Когда очередь заполнена до отказа, системный вызов connect на стороне клиента возвращает признак ошибки с кодом ECONNREFUSED.

Прием соединений на стороне сервера выполняется системным вызовом accept:

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

#include <sys/socket.h>

int accept (

int socket_fd, /* файловый дескриптор сокета */

struct sockaddr *sa, /* адрес сокета или NULL*/

socklen_t *sa_len /* длина адреса */

);

/* Возвращает файловый дескриптор или -1 в случае ошибки (код ошибки - в errno) */

Обычно системный вызов accept блокируется до поступления запроса на соединение от другого процесса, после чего создает новый сокет для принятого соединения и возвращает новый файловый дескриптор. Если аргумент sa не NULL, по указанному адресу записываются сведения о сокете, соединение с которым было принято. При этом в аргумент sa_len передается указатель на переменную, которая хранит размер области памяти, отведенной под сведения о сокете. По возвращении из системного вызова эта переменная будет содержать фактический объем данных, записанных в sa. Клиент после создания сокета вызывает connect, которому передает адрес сервера:

connect - устанавливает соединение

#include <sys/socket.h>

int connect (

int socket_fd, /* файловый дескриптор сокета */

const struct sockaddr *sa, /* адрес сокета */

socklen_t sa_len /* длина адреса */

);

/* Возвращает 0 в случае успеха или -1 в случае ошибки (код ошибки - в errno) */

Системный вызов connect блокируется до того момента, как запрос на соединение будет принят сервером, но он не возвращает новый файловый дескриптор – клиент выполняет операции ввода-вывода над прежним дескриптором. Если установлен флаг O_NONBLOCK, вызов connect не будет ожидать установления соединения, а сразу же вернет признак ошибки с кодом EINPROGRESS. Запрос на соединение при этом не теряется, а помещается в очередь. Все последующие обращения к connect в этот период будут заканчиваться ошибкой с кодом EALREADY. После того как соединение будет установлено, то можно использовать файловый дескриптор по своему усмотрению.