Я обеспокоен тем, что происходит, когда соединение с клиентом становится
неактивен, например, из-за разрыва сетевого соединения таким образом, что
не отправляет TCP RST или FIN.
Если соединение таким образом потеряно (возможно, из-за того, что клиентская система отключена или физически отключена), то TCP на сервере обнаружит разрыв соединения, поскольку он не будет получать подтверждения отправленных данных. Для отказа TCP может потребоваться несколько минут, но в этом случае это не кажется большой проблемой.
В худшем случае клиентская система остается подключенной, но клиентский процесс перестает считывать данные из подключения. В этом случае отправленные данные будут накапливаться на клиенте до тех пор, пока клиентский сокет не заполнит приемный буфер, а затем отправленные данные будут накапливаться на сервере - сначала в буфере отправки сокета в ядре, а затем в памяти процесса сервера.
Я несколько удивлен, что метод send () не вызывается с
ключевое слово await в асинхронном методе.
ws
предшествует асинхронному ожиданию и обещаниям по годам. Я полагаю, что API в конечном итоге будет модернизирован, но это еще не произошло.
Метод send () является просто очередью
все данные для отправки? Что если буферы сокетов заполнятся, может
блок send () таким образом, что вызывает голод других клиентов, кроме
заблокирован один?
WebSocket.send
в конечном итоге вызывает Socket.write
встроенного Net
модуля. (См. Функцию sendFrame
в нижней части https://github.com/websockets/ws/blob/master/lib/sender.js для этого вызова и см. https://nodejs.org/docs/latest-v8.x/api/net.html#net_class_net_socket для документации класса Socket
.)
Socket.write
буферизует данные в пользовательском процессе, если ядро не может немедленно принять данные. Данные буферизуются отдельно для каждого Socket
, поэтому обычно эта буферизация не влияет на передачу на других Socket
, подключенных к другим клиентам. Тем не менее, нет никаких ограничений на количество данных, которые один Socket
будет буферизировать. В крайнем случае буферизованные данные Socket
могут занимать всю память серверного процесса, и в результате сбой сервера будет мешать доставке данных всем клиентам.
Есть несколько способов избежать этой проблемы. На ум приходят два простых метода:
предоставляет аргумент обратного вызова завершения для вызова send
. Этот обратный вызов будет передан вызову Socket.write
, который вызовет обратный вызов, когда все эти данные write
будут записаны в ядро. Если ваш сервер воздерживается от отправки большего количества данных этому клиенту до тех пор, пока не сработает обратный вызов, объем данных, буферизованных в пространстве пользователя для этого соединения, будет ограничен размером, близким к размеру самого последнего send
. (Это не будет точно такой размер, потому что буферизованные данные будут включать кадрирование WebSocket, а также кадрирование SSL и заполнение, если ваше соединение зашифровано, поверх исходных данных, передаваемых в send
.) Или
проверьте свойство bufferSize
соединения Socket
перед подготовкой к send
данным по этому соединению. bufferSize
указывает объем данных, которые в настоящее время буферизируются в пространстве пользователя для этого сокета. Если он ненулевой, пропустите send
для этого клиента.