Сокеты
Виды сокетов
| Домен |
Тип |
Описание |
| AF_UNIX |
Локальный |
Адрес — путь в файловой системе |
| AF_INET |
Сетевой |
Адрес — IP + порт |
| Тип |
Протокол |
Особенности |
| SOCK_STREAM |
TCP |
С установлением соединения, надёжная доставка |
| SOCK_DGRAM |
UDP |
Без соединения, датаграммы |
| SOCK_SEQPACKET |
— |
Последовательные пакеты с границами |
Модель клиент-сервер (SOCK_STREAM)
| Сервер |
Клиент |
| socket() | socket() |
| bind() | — |
| listen() | — |
| accept() | connect() |
| recv() / send() | send() / recv() |
| shutdown() | shutdown() |
| close() | close() |
Для датаграмм (SOCK_DGRAM) используются sendto() и recvfrom() без listen() и accept().
Системные вызовы
int socket(int domain, int type, int protocol);
int bind(int fd, const struct sockaddr *addr, socklen_t len);
int listen(int fd, int backlog);
int connect(int fd, const struct sockaddr *addr, socklen_t len);
int accept(int fd, struct sockaddr *addr, socklen_t *len);
ssize_t send(int fd, const void *buf, size_t len, int flags);
ssize_t recv(int fd, void *buf, size_t len, int flags);
int shutdown(int fd, int how);
int close(int fd);
Адресные структуры
/* AF_UNIX */
struct sockaddr_un {
sa_family_t sun_family; /* AF_UNIX */
char sun_path[108]; /* путь к файлу сокета */
};
/* AF_INET */
struct sockaddr_in {
sa_family_t sin_family; /* AF_INET */
in_port_t sin_port; /* порт (сетевой порядок байт) */
struct in_addr sin_addr; /* IP-адрес */
};
Вспомогательные функции
uint16_t htons(uint16_t hostshort); /* хост -> сеть (порт) */
uint32_t htonl(uint32_t hostlong); /* хост -> сеть (адрес) */
in_addr_t inet_addr(const char *cp); /* строка IP -> число */
Пример TCP-сервера
#include <sys/socket.h>
#include <netinet/in.h>
int fd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(7900);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(fd, (struct sockaddr *)&addr, sizeof(addr));
listen(fd, 5);
int client = accept(fd, NULL, NULL);
char buf[2048];
int n = recv(client, buf, sizeof(buf)-1, 0);
buf[n] = '\0';
send(client, buf, n, 0); /* эхо */
shutdown(client, SHUT_RDWR);
close(client);
close(fd);
Shutdown — режимы закрытия
| Флаг |
Значение |
Действие |
| SHUT_RD | 0 | Закрыть для чтения |
| SHUT_WR | 1 | Закрыть для записи |
| SHUT_RDWR | 2 | Закрыть полностью |
netstat -a # показать все сокеты