Unix Socket - Основные функции
В этой главе описываются основные функции сокетов, необходимые для написания полного TCP-клиента и сервера.
На следующей диаграмме показано полное взаимодействие клиента и сервера -
Функция сокета
Чтобы выполнить сетевой ввод-вывод, первое, что должен сделать процесс, - это вызвать функцию сокета, указав тип желаемого протокола связи, семейство протоколов и т. Д.
#include <sys/types.h>
#include <sys/socket.h>
int socket (int family, int type, int protocol);
Этот вызов возвращает дескриптор сокета, который вы можете использовать в последующих системных вызовах или -1 в случае ошибки.
Параметры
family - Он определяет семейство протоколов и является одной из констант, показанных ниже -
Семья | Описание |
---|---|
AF_INET | Протоколы IPv4 |
AF_INET6 | Протоколы IPv6 |
AF_LOCAL | Протоколы домена Unix |
AF_ROUTE | Маршрутные сокеты |
AF_KEY | Кет розетка |
В этой главе не рассматриваются другие протоколы, кроме IPv4.
type- В нем указывается, какой тип сокета вы хотите. Может принимать одно из следующих значений -
Тип | Описание |
---|---|
SOCK_STREAM | Потоковое гнездо |
SOCK_DGRAM | Сокет дейтаграмм |
SOCK_SEQPACKET | Последовательный пакетный сокет |
SOCK_RAW | Сырая розетка |
protocol - Аргумент должен быть установлен для конкретного типа протокола, указанного ниже, или 0, чтобы выбрать систему по умолчанию для данной комбинации семейства и типа -
Протокол | Описание |
---|---|
IPPROTO_TCP | Транспортный протокол TCP |
IPPROTO_UDP | Транспортный протокол UDP |
IPPROTO_SCTP | Транспортный протокол SCTP |
Подключения функции
Функция подключения используется TCP-клиентом для установления соединения с TCP-сервером.
#include <sys/types.h>
#include <sys/socket.h>
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
Этот вызов возвращает 0, если он успешно соединяется с сервером, иначе он возвращает -1 при ошибке.
Параметры
sockfd - Это дескриптор сокета, возвращаемый функцией сокета.
serv_addr - Это указатель на struct sockaddr, который содержит IP-адрес и порт назначения.
addrlen - Установите значение sizeof (struct sockaddr).
Связывают функции
Функция привязки назначает сокету адрес локального протокола. В случае Интернет-протоколов адрес протокола представляет собой комбинацию 32-битного адреса IPv4 или 128-битного адреса IPv6 вместе с 16-битным номером порта TCP или UDP. Эта функция вызывается только TCP-сервером.
#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, struct sockaddr *my_addr,int addrlen);
Этот вызов возвращает 0, если он успешно привязывается к адресу, в противном случае он возвращает -1 при ошибке.
Параметры
sockfd - Это дескриптор сокета, возвращаемый функцией сокета.
my_addr - Это указатель на struct sockaddr, который содержит локальный IP-адрес и порт.
addrlen - Установите значение sizeof (struct sockaddr).
Вы можете автоматически указать свой IP-адрес и порт
Значение 0 для номера порта означает, что система выберет случайный порт, а значение INADDR_ANY для IP-адреса означает, что IP-адрес сервера будет назначен автоматически.
server.sin_port = 0;
server.sin_addr.s_addr = INADDR_ANY;
NOTE- Все порты ниже 1024 зарезервированы. Вы можете установить порт выше 1024 и ниже 65535, если только они не используются другими программами.
Слушать функции
Функция прослушивания вызывается только TCP-сервером и выполняет два действия:
Функция прослушивания преобразует неподключенный сокет в пассивный, указывая, что ядро должно принимать входящие запросы на соединение, направленные на этот сокет.
Второй аргумент этой функции указывает максимальное количество соединений, которое ядро должно поставить в очередь для этого сокета.
#include <sys/types.h>
#include <sys/socket.h>
int listen(int sockfd,int backlog);
Этот вызов возвращает 0 в случае успеха, иначе он возвращает -1 в случае ошибки.
Параметры
sockfd - Это дескриптор сокета, возвращаемый функцией сокета.
backlog - Это количество разрешенных подключений.
Принимает функцию
Функция accept вызывается TCP-сервером, чтобы вернуть следующее завершенное соединение с начала очереди завершенных соединений. Подпись вызова выглядит следующим образом -
#include <sys/types.h>
#include <sys/socket.h>
int accept (int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);
Этот вызов возвращает неотрицательный дескриптор в случае успеха, иначе он возвращает -1 в случае ошибки. Предполагается, что возвращенный дескриптор является дескриптором клиентского сокета, и все операции чтения-записи будут выполняться на этом дескрипторе для связи с клиентом.
Параметры
sockfd - Это дескриптор сокета, возвращаемый функцией сокета.
cliaddr - Это указатель на struct sockaddr, который содержит IP-адрес и порт клиента.
addrlen - Установите значение sizeof (struct sockaddr).
Посыла Функция
Функция отправки используется для отправки данных через сокеты потоков или сокеты датаграмм CONNECTED. Если вы хотите отправлять данные через НЕ ПОДКЛЮЧЕННЫЕ сокеты дейтаграммы, вы должны использовать функцию sendto ().
Вы можете использовать системный вызов write () для отправки данных. Его подпись выглядит следующим образом -
int send(int sockfd, const void *msg, int len, int flags);
Этот вызов возвращает количество отправленных байтов, иначе в случае ошибки он вернет -1.
Параметры
sockfd - Это дескриптор сокета, возвращаемый функцией сокета.
msg - Это указатель на данные, которые вы хотите отправить.
len - Это длина данных, которые вы хотите отправить (в байтах).
flags - Установлен на 0.
RECV Функция
Функция recv используется для получения данных через сокеты потока или сокеты датаграмм CONNECTED. Если вы хотите получать данные через НЕ ПОДКЛЮЧЕННЫЕ сокеты дейтаграмм, вы должны использовать recvfrom ().
Вы можете использовать системный вызов read () для чтения данных. Этот вызов объясняется в главе о вспомогательных функциях.
int recv(int sockfd, void *buf, int len, unsigned int flags);
Этот вызов возвращает количество байтов, считанных в буфер, в противном случае при ошибке возвращается -1.
Параметры
sockfd - Это дескриптор сокета, возвращаемый функцией сокета.
buf - Это буфер для чтения информации.
len - Это максимальная длина буфера.
flags - Установлен на 0.
SendTo Функция
Функция sendto используется для отправки данных через НЕПОДКЛЮЧЕННЫЕ сокеты дейтаграммы. Его подпись выглядит следующим образом -
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
Этот вызов возвращает количество отправленных байтов, в противном случае он возвращает -1 в случае ошибки.
Параметры
sockfd - Это дескриптор сокета, возвращаемый функцией сокета.
msg - Это указатель на данные, которые вы хотите отправить.
len - Это длина данных, которые вы хотите отправить (в байтах).
flags - Установлен на 0.
to - Это указатель на struct sockaddr для хоста, на который должны быть отправлены данные.
tolen - Он установлен на sizeof (struct sockaddr).
Recvfrom Функция
Функция recvfrom используется для получения данных из НЕПОДКЛЮЧЕННЫХ сокетов дейтаграммы.
int recvfrom(int sockfd, void *buf, int len, unsigned int flags struct sockaddr *from, int *fromlen);
Этот вызов возвращает количество байтов, прочитанных в буфер, в противном случае он возвращает -1 в случае ошибки.
Параметры
sockfd - Это дескриптор сокета, возвращаемый функцией сокета.
buf - Это буфер для чтения информации.
len - Это максимальная длина буфера.
flags - Установлен на 0.
from - Это указатель на struct sockaddr для хоста, с которого должны быть прочитаны данные.
fromlen - Он установлен на sizeof (struct sockaddr).
Близко Функция
Функция закрытия используется для закрытия связи между клиентом и сервером. Его синтаксис следующий -
int close( int sockfd );
Этот вызов возвращает 0 в случае успеха, иначе он возвращает -1 в случае ошибки.
Параметры
sockfd - Это дескриптор сокета, возвращаемый функцией сокета.
Выключение функции
Функция выключения используется для корректного закрытия связи между клиентом и сервером. Эта функция дает больше контроля по сравнению с функцией закрытия . Ниже приведен синтаксис выключения -
int shutdown(int sockfd, int how);
Этот вызов возвращает 0 в случае успеха, иначе он возвращает -1 в случае ошибки.
Параметры
sockfd - Это дескриптор сокета, возвращаемый функцией сокета.
how - Поставьте одну из цифр -
0 - указывает, что получение не разрешено,
1 - указывает, что отправка не разрешена, и
2- указывает, что и отправка, и получение не разрешены. Когда how установлено на 2, это то же самое, что и close ().
Выберите Функции
Функция выбора указывает, какой из указанных файловых дескрипторов готов к чтению, готов к записи или имеет состояние ошибки.
Когда приложение вызывает recv или recvfrom , оно блокируется до поступления данных для этого сокета. Приложение может выполнять другую полезную обработку, пока входящий поток данных пуст. Другая ситуация - когда приложение получает данные из нескольких сокетов.
Вызов recv или recvfrom для сокета, у которого нет данных во входной очереди, предотвращает немедленный прием данных из других сокетов. Вызов функции select решает эту проблему, позволяя программе опрашивать все дескрипторы сокетов, чтобы узнать, доступны ли они для неблокирующих операций чтения и записи.
Ниже приведен синтаксис select -
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout);
Этот вызов возвращает 0 в случае успеха, иначе он возвращает -1 в случае ошибки.
Параметры
nfds- Он определяет диапазон тестируемых файловых дескрипторов. Функция select () проверяет файловые дескрипторы в диапазоне от 0 до nfds-1.
readfds- Он указывает на объект типа fd_set, который на входе определяет файловые дескрипторы, которые необходимо проверить на готовность к чтению, а на выходе указывает, какие файловые дескрипторы готовы к чтению. Может быть NULL, чтобы указать пустой набор.
writefds- Он указывает на объект типа fd_set, который на входе определяет файловые дескрипторы, которые необходимо проверить на готовность к записи, а на выходе указывает, какие файловые дескрипторы готовы к записи. Может быть NULL, чтобы указать пустой набор.
exceptfds- Он указывает на объект типа fd_set, который на входе определяет файловые дескрипторы, которые необходимо проверить на наличие ожидающих условий ошибки, а на выходе указывает, какие файловые дескрипторы имеют ожидающие условия ошибки. Может быть NULL, чтобы указать пустой набор.
timeout- Он указывает на структуру timeval, которая указывает, как долго вызов select должен опрашивать дескрипторы для доступной операции ввода-вывода. Если значение тайм-аута равно 0, select вернется немедленно. Если аргумент тайм-аута равен ПУСТО (NULL), то select будет блокироваться до тех пор, пока хотя бы один дескриптор файла / сокета не будет готов для доступной операции ввода-вывода. В противном случае select вернется после того, как истечет время в таймауте, ИЛИ когда хотя бы один дескриптор файла / сокета будет готов для операции ввода-вывода.
Возвращаемое значение select - это количество дескрипторов, указанных в наборах файловых дескрипторов, готовых для ввода-вывода. Если достигнут предел времени, указанный в поле тайм-аута, выберите return 0. Существуют следующие макросы для управления набором дескрипторов файла:
FD_CLR(fd, &fdset)- Сбрасывает бит для файлового дескриптора fd в наборе файловых дескрипторов fdset.
FD_ISSET(fd, &fdset)- Возвращает ненулевое значение, если бит для дескриптора файла fd установлен в наборе дескрипторов файла, на который указывает fdset , и 0 в противном случае.
FD_SET(fd, &fdset) - Устанавливает бит для файлового дескриптора fd в наборе файловых дескрипторов fdset.
FD_ZERO(&fdset) - Инициализирует набор дескрипторов файла fdset, чтобы он имел нулевые биты для всех дескрипторов файлов.
Поведение этих макросов не определено, если аргумент fd меньше 0 или больше или равен FD_SETSIZE.
пример
fd_set fds;
struct timeval tv;
/* do socket initialization etc.
tv.tv_sec = 1;
tv.tv_usec = 500000;
/* tv now represents 1.5 seconds */
FD_ZERO(&fds);
/* adds sock to the file descriptor set */
FD_SET(sock, &fds);
/* wait 1.5 seconds for any data to be read from any single socket */
select(sock+1, &fds, NULL, NULL, &tv);
if (FD_ISSET(sock, &fds)) {
recvfrom(s, buffer, buffer_len, 0, &sa, &sa_len);
/* do something */
}
else {
/* do something else */
}