Что такое сокет
Что проверяют
Понимаете ли вы, что происходит под привычными клиентами и фреймворками. Вопрос базовый, но ответ быстро показывает, работал ли человек с сетью руками: где кончается ответственность операционной системы, где начинается ваш протокол и почему сетевой код почти всегда пишется циклом.
Как отвечать
Сокет это конечная точка обмена, дескриптор, который операционная система выдаёт процессу. Установленное TCP-соединение опознаётся пятёркой: протокол, локальный адрес и порт, удалённый адрес и порт, поэтому на одном серверном порту спокойно живут тысячи соединений.
Два основных вида: SOCK_STREAM поверх TCP даёт соединение, подтверждения, порядок и поток байт; SOCK_DGRAM поверх UDP работает без соединения и без гарантий, зато сохраняет границы датаграмм.
Порядок вызовов на сервере: socket, bind, listen, accept, дальше recv и send, затем close. На клиенте: socket, connect, обмен, close.
import socket
srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
srv.bind(("127.0.0.1", 9000))
srv.listen(128)
with srv:
conn, addr = srv.accept()
with conn:
chunk = conn.recv(4096) # вернет до 4096 байт, а не ровно столько
conn.sendall(b"ok")Главное про TCP: это поток без границ сообщений, поэтому свой протокол кадрирования обязателен, длиной в префиксе или разделителем. В Python блокирующий сокет занимает поток целиком, и на многих соединениях берут asyncio.
Где спотыкаются
Читают ровно один раз и считают, что получили сообщение целиком. Одна отправка может прийти несколькими кусками, а две отправки склеиться в одно чтение, поэтому читать нужно в цикле до нужной длины.
Путают send и sendall: первый возвращает число реально отправленных байт и вправе отправить не всё, второй дожимает остаток сам.
Забывают про таймауты и закрытие. Сокет без settimeout зависает навсегда при пропавшей сети, а неосвобождённый серверный порт после перезапуска встречает ошибкой занятого адреса, от которой спасает SO_REUSEADDR.