Принять входящее соединение
- Прототип
-
#include <sys/types.h>
#include <sys/socket.h>
int accept(int s, struct sockaddr *addr, socklen_t
*addrlen);
- Описание
-
Когда ты создал сокет типа SOCK_STREAM и настроил его на ожидание соединений с помощью listen(), вызови accept(), чтобы получить новый дескриптор сокета для дальнейшего взаимодействия с соединившимся клиентом.
Старый сокет - который ждет соединений - продолжает ждать, и для него можно опять вызывать accept().
s |
Ожидающий сокет. |
addr |
Сюда возвращается адрес соединившегося клиента. |
addrlen |
Сюда возвращается sizeof() структуры, возвращенной в addr. Если ты наверняка получаешь struct sockaddr_in, его можно спокойно проигнорировать. |
accept() блокирует, и ты можешь использовать select(), чтобы узнать, готов ли слушающий сокет "к чтению". На самом деле, это значит, что у него есть новое соединение! Также можно установить флаг O_NONBLOCK с помощью fcntl(), и он не будет блокировать, возвращая вместо этого -1 и сохраняя EWOULDBLOCK в errno.
Дескриптор сокета, возвращаемый функцией accept(), открыт и соединен с удаленным хостом. Его нужно закрыть с помощью close(), когда он будет не нужен.
- Возвращаемое значение
-
accept() возвращает новый дескриптор сокета, или -1 при ошибке, сохраняя ее номер в errno.
- Пример
-
int s, s2;
struct sockaddr_in myaddr, remoteaddr;
socklen_t remoteaddr_len;
myaddr.sin_family = AF_INET;
myaddr.sin_port = htons(3490); // порт соединения
myaddr.sin_addr.s_addr = INADDR_ANY; // автоматический выбор IP-адреса
s = socket(PF_INET, SOCK_STREAM, 0);
bind(s, (struct sockaddr*)myaddr, sizeof(myaddr));
listen(s, 10); // сделать s слушающим (серверным) сокетом
for(;;) {
s2 = accept(s, &remoteaddr, &remoteaddr_len);
// теперь можно использовать send() и recv()
// для обмена данными с клиентом через сокет s2
}
|
- См. также
-
socket(),
listen(),
struct sockaddr_in
|