Как принудительно сбросить сокет в Node.js? - PullRequest
1 голос
/ 25 апреля 2019

Я получаю ошибки 'read ECONNRESET' из моего приложения Node.js (это могут быть соединения с клиентом или сервером, я не уверен).

В качестве решения этой проблемы я бы хотел провести локальное тестирование и, желательно, настроить для него автоматические тесты. Я хочу написать Node-клиент и сервер, который будет перезагружать соединения, как только они будут установлены, чтобы я мог это проверить.

Настройка сервера / клиента проста, но я не уверен, как принудительно сбросить соединение, чтобы воспроизвести проблему, которую я вижу здесь. Документация по сокету Node нигде не упоминает перезагрузки

Есть идеи?

1 Ответ

0 голосов
/ 01 мая 2019

Насколько я могу судить, идеального решения для этого не существует, но я нашел два варианта для этого и подал ошибку в Node, чтобы добавить надлежащую поддержку .

Для моей проблемы (запустите HTTP-запрос, затем RST сокет) я нашел два решения:

Уничтожить сокет непосредственно перед получением пакета

const net = require('net');

const socket = new net.Socket();
socket.connect(8000, "127.0.0.1", () => {
    socket.write(
        'GET / HTTP/1.1\n' +
        'Host: example.com\n\n'
    );
    setTimeout(() => socket.destroy(), 0);
});

Если вы знаете, что собираетесьПолучив пакет по этому соединению, вы можете destroy() сокет сразу же.Это не отправляет RST, но отправляет RST в ответ на будущие пакеты.

Чтобы сделать это, вам нужно поспешно уничтожить сокет после того, как ваше сообщение написано, но до того, как ответ придет.Для локальных соединений это может быть сложно - setTimeout(() => socket.destroy(), 0) - самое надежное решение, которое я нашел, но YMMV, и оно, конечно, не гарантировано.Я ожидал, что обратный вызов write() будет работать более надежно, но, похоже, он не работает.

Используйте другой язык (например, Python)

Теперь я вернулся к использованиюPython для тестирования, так как он имеет прямой контроль над этим.Чтобы отправить пакет RST в Python:

import socket
import time
import struct

TCP_IP = '127.0.0.1'
TCP_PORT = 8000

# Connect to the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
s.connect((TCP_IP, TCP_PORT))

# Start an HTTP request
s.send("GET / HTTP/1.1\r\n\
Host: example.com\r\n\
\r\n")
time.sleep(0.1)

# RST the socket without reading the response
# See https://stackoverflow.com/a/6440364/68051 for context
s.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
s.close()

Надеемся, что команда Node скоро рассмотрит вопрос о добавлении аналогичной поддержки (см. https://github.com/nodejs/node/issues/27428),, но выше может быть полезно в это время.

...