如何强制重置Node.js中的套接字?
How to forcibly reset a socket in Node.js?
我从我的 Node.js 应用程序收到 'read ECONNRESET' 个错误(可能是客户端或服务器连接,我不确定)。
作为解决这些问题的一部分,我想进行一些本地测试,最好为其设置自动化测试。我想编写一个 Node 客户端和服务器,在连接建立后立即硬重置连接,以便我可以对此进行测试。
设置 server/client 很简单,但我不确定如何强制重置连接以重现我在这里看到的问题。节点 socket docs 不要在任何地方提及重置
有什么想法吗?
据我所知,对此没有完美的解决方案,但我找到了两个选择,filed a bug against Node to add proper support。
对于我的问题(启动 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 进行测试,因为它可以直接控制这一点。在 Python 中发送 RST 数据包:
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 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),但以上内容在此期间可能会有所帮助。
类似于已接受的答案,但可能更直接:
const net = require('net');
const client = net.connect(8124, "localhost", () => {
console.log('connected!');
client.destroy(new Error('ECONNRESET'))
});
来自 Simulate an ECONNRESET error on a Node.js net.Socket instance
我从我的 Node.js 应用程序收到 'read ECONNRESET' 个错误(可能是客户端或服务器连接,我不确定)。
作为解决这些问题的一部分,我想进行一些本地测试,最好为其设置自动化测试。我想编写一个 Node 客户端和服务器,在连接建立后立即硬重置连接,以便我可以对此进行测试。
设置 server/client 很简单,但我不确定如何强制重置连接以重现我在这里看到的问题。节点 socket docs 不要在任何地方提及重置
有什么想法吗?
据我所知,对此没有完美的解决方案,但我找到了两个选择,filed a bug against Node to add proper support。
对于我的问题(启动 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 进行测试,因为它可以直接控制这一点。在 Python 中发送 RST 数据包:
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 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),但以上内容在此期间可能会有所帮助。
类似于已接受的答案,但可能更直接:
const net = require('net');
const client = net.connect(8124, "localhost", () => {
console.log('connected!');
client.destroy(new Error('ECONNRESET'))
});
来自 Simulate an ECONNRESET error on a Node.js net.Socket instance