한국어English日本語简体中文繁體中文DeutschไทยTiếng ViệtРусскийPortuguês (Brasil)EspañolBahasa Indonesia

Анатомия игровых лагов › L8 Сокеты и протоколы

Потеря последних данных при принудительном закрытии через RST SO_LINGER, abrupt RST

ID причины sk-linger · Основной ответственный Команда разработки · Разработка сервера

Открыть карточку в основной версии с иллюстрациями и экспериментами →

Если сервер резко рвёт соединение, последнее отправленное сообщение или подтверждение сохранения пропадает.

Почему Сервер закрывает соединение принудительно (RST). Так бывает, если SO_LINGER выставлен в 0 с или сокет закрыт, когда полученные данные ещё не дочитаны → Следствие Причина кика и последние данные, которые ещё передавались, выбрасываются → На экране Сообщение «Соединение закрыто из-за неизвестной ошибки» без видимой причины

Симптомы
Дисконнект
Факторы
Потери
У кого
Только у меня
Когда
Изредка, случайно
Ответственные
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Отправив причину, сначала закрыть только направление отправки (shutdown), дочитать полученные данные, пока другая сторона не закроет соединение, и только потом закрыть сокет. Не использовать SO_LINGER с 0 с.
На графике
Случайные всплески · число соединений, завершённых через RST
Где смотреть
Посмотреть прирост TcpExtTCPAbortOnData (закрыто через RST с неотправленными данными, SO_LINGER 0 с) и TcpExtTCPAbortOnClose (закрыто с непрочитанными данными) в nstat -az, а в захвате пакетов на стороне сервера проверить, уходит ли в момент обрыва RST вместо FIN
Подтверждает
В моменты жалоб на «Соединение закрыто из-за неизвестной ошибки» сервер отправляет RST, а AbortOnData и AbortOnClose растут
Опровергает
Если сервер штатно закрыл соединение через FIN, а причина не показана, дело в обработке закрытия на клиенте
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)

Источники

  1. closesocket function (winsock.h) Microsoft
    Если включить SO_LINGER со временем 0, закрытие становится принудительным: соединение сразу сбрасывается, а неотправленные данные теряются
  2. RFC 9293: Transmission Control Protocol (TCP) IETF
    Если закрыть сокет с непрочитанными полученными данными, отправляется RST, чтобы сообщить о потере данных
  3. Graceful Shutdown, Linger Options, and Socket Closure Microsoft
    Порядок: сначала закрыть только отправку через shutdown, а сокет закрывать после того, как пришло уведомление о закрытии от другой стороны
  4. SNMP counter Linux kernel
    TcpExtTCPAbortOnData: соединение закрыто через RST с неотправленными данными (например, при SO_LINGER 0 с). TcpExtTCPAbortOnClose: сокет закрыт с непрочитанными данными, и отправлен RST

Смотрите также

Тот же слой: L8 Сокеты и протоколы

Причины с тем же симптомом (Дисконнект) на других слоях

Карточка в основной версии с иллюстрациями и экспериментами