Характер этого вызова предполагает создание виртуального канала и, таким образом, используется для предварительного установления связи между коммуникационными узлами. В этом случае клиенту нет необходимости явно связывать сокет с помощью системного вызова sockfd
, для которого система автоматически выбирает приемлемые значения локального адреса и процесса. Удаленный узел определяется аргументом servaddr
, который указывает на адрес сервера, a addrlen
задает его длину.
Вызов
Следующие два вызова используются сервером только при взаимодействии, основанном на предварительном создании виртуального канала между сервером и клиентом.
Системный вызов
#include
#include
int listen(int sockfd, int backlog);
Здесь параметр sockfd
определяет сокет, который будет использоваться для получения запросов. Предполагается, что сокет был предварительно связан с известным адресом. Параметр backlog
указывает максимальное число запросов на установление связи, которые могут ожидать обработки сервером.[45]
Фактическую обработку запроса клиента на установление связи производит системный вызов
#include
#include
int accept(int sockfd, struct sockaddr *clntaddr,
int* addrlen);
Вызов sockfd
, и таким образом завершает создание виртуального канала со стороны сервера. Одновременно clntaddr
и его размер addrlen
. Новый сокет используется для обслуживания созданного виртуального канала, а полученный адрес клиента исключает анонимность последнего. Дальнейший типичный сценарий взаимодействия имеет вид:
sockfd = socket(...);
Создать сокет
bind(sockfd, ...);
Связать его с известным локальным адресом
listen(sockfd, ...);
Организовать очередь запросов
for(;;) {
newsockfd = accept(sockfd, ...);
Получить запрос
if (fork == 0) {
Породить дочерний процесс
close(sockfd);
Дочерний процесс
...
exit(0);
} else
close(newsockfd);
Родительский процесс
}
В этом сценарии, в то время как дочерний процесс обеспечивает фактический обмен данными с клиентом, родительский процесс продолжает "прослушивать" поступающие запросы, порождая для каждого из них отдельный процесс-обработчик. Очередь позволяет буферизовать запросы на время, пока сервер завершает вызов newsockfd
, полученный в результате вызова sockfd
определена только локальная часть канала. Это позволяет серверу продолжать использовать sockfd
для "прослушивания" последующих запросов.
Наконец, если для сокетов потока при приеме и передаче данных могут быть использованы стандартные вызовы
#include
#include
int send(int s, const char *msg, int len, int flags);
int sendto(int s, const char *msg, int len, int flags,
const struct sockaddr* toaddr, int tolen);
int recv(int s, char *buf, int len, int flags);
int recvfrom(int s, char *buf, int len, int flags,
struct sockaddr* fromaddr, int* fromlen);
Функции