我有兩個后端。后端 A 和后端 B。
。
后端B使用運行在埠4243的套接字服務器來發送和接收資訊。
然后,通過后端 A,我需要捕捉該資訊并保存它。但是我必須在后端 A 上有一個在埠 4243 上運行的 socket 服務器。
問題是,當我在運行后端B后運行后端A時,我收到了錯誤"EADDRINUSE",因為我在兩個應用程式上使用相同的主機:埠。
如果我在后端 A 中使用 Python,問題就會消失,因為我有一個名為SO_REUSEADDR的套接字配置。
這里我們有一些例子:
但是,使用Python代碼,套接字成功連接:
我不知道該怎么做。
我不知道該怎么做 :(
我希望能在這里得到一些幫助。
編輯1
順便說一下,
lsof命令,給我的JavaScript后端拋出這樣的輸出:而Python后端則有這樣的輸出:
編輯2
編輯2
這似乎真的是JavaScript的一個問題。我還發現這個片段:
var net = require('net')。 function startServer(port, host, callback) { var server = net.createServer()。 server.listen(port, host, function(/span>) { callback(undefined, server)。 }); server.on('error'/span>, function(error) { console.error('Ah damn! ', error)。 callback(error)。 }); } startServer(4000, '0.0.0.0'/span>, function(error, wildcardServer) { if(錯誤) 回傳。 startServer(4000, '127.0.0.1', function(error, localhostServer) { if(錯誤)回傳。 console.log(' Started both servers! ')。 }); });來自這個帖子。 https://medium.com/@eplawless/node-js-is-a-liar-sometimes-8a28196d56b6
正如作者所說:
好吧,這將列印出 "啟動了兩個服務器!"這正是我們不希望看到的。
但是對我來說,我得到的不是列印,而是一個錯誤:
Ah damn! Error。listen EADDRINUSE: address already in use 127。 0.0.1:4000。 at Server。 setupListenHandle [as _listen2] (node: net: 1319: 16) at listenInCluster (node: net:1367:12) at doListen (node: net:1505:7) at processTicksAndRejections (node: internal/process/task_queues:84:21) { 代碼。'EADDRINUSE'。 errno: -98, syscall: 'listen', 地址。'127.0.0.1', 埠。4000 }我真的不能讓它運行并列印出 "啟動兩個服務器!"。
因為這就是我想讓我的代碼做的事情。
編輯3
這就是Python服務器套接字。https://gitlab.com/d3tn/ud3tn/-/blob/master/tools/aap/aap_receive.py
這是重要的部分:
addr = (args.tcp[0], int(args.tcp[1]) # args.tcp[0] = "localhost", args.tcp[1] = "4243" with AAPTCPClient(address=addr) as aap_client: aap_client.register(args.agentid) # args.agentid = "bundlesink" run_aap_recv(aap_client, args.count, args.verify_pl)它創建了一個AAPTCPClient,AAPTCPClient唯一做的事情是:
它創建了一個AAPTCPClient。
def __init__(self, socket, address) 。 self.socket = socket self.address = address self.node_eid = None: self.socket = socket, address = address. self.agent_id = Nonedef register(self, agent_id=None)。 ""試圖注冊指定的代理識別符號。 Args: agent_id。要注冊的代理識別符號。如果沒有。 uuid.uuid4()被呼叫來生成一個。 "" self.agent_id = agent_id or str(uuid.uuid4() ) logger.info(f "Sending REGISTER message for '{agent_id}' ...") msg_ack = self.send( AAPMessage(AAPMessageType.REGISTER, self.agent_id) ) assert msg_ack.msg_type == AAPMessageType.ACK logger.info("收到ACK訊息!") def send(self, aap_msg)。 ""將提供的`AAPMessage`序列化并發送至AAP端點。 Args: aap_msg: 要發送的`AAPMessage'。 "" self.socket.send(aap_msg.serialize()) return self.receive() def receive(self)。 ""接收并回傳下一個`AAPMessage'。""。 buf = bytearray() msg = None() while msg is None: data = self.socket.recv(1) if not data: logger.info("Disconnected") return None buf = data try: msg = AAPMessage.parse(buf) except InsufficientAAPDataError: 繼續。 return msg我沒有看到任何系結,我不明白為什么python代碼可以呼叫"
socket.recv",但在我的JavaScript代碼中卻不能做"netServer.listen"。我認為這應該是一樣的。uj5u.com熱心網友回復:
有一些事情需要澄清。 1.) 客戶端使用bind系統呼叫,內核會自動選擇源埠。
它通過檢查 sys local_portrange sysctl 設定來實作。
1.) 如果你想把客戶端系結到一個靜態的源埠,請確保選擇一個 local_portrange 范圍之外的 TCP 埠!
2.
2.) 你不能訂閱事件 "*",相反,你必須訂閱事件"data"來接收訊息。
為了達到最佳效果,你還應該訂閱"error"事件,以防出現錯誤!
SO_REUSEADDR和SO_REUSEPORT有何不同?
https://idea.popcount.org/2014-04-03-bind-before-connect/
因此,對于所有想要深入挖掘使用node.js的網路的初學者來說......
一個作業的服務器實體。
一個作業服務器的例子:
// Step 0: Create the netServer and the netClient // var HOST = 'localhost'。 var PORT = 4243; var AGENT_ID = 'SO_REUSEADDR DEMO'/span>; var net = require('net')。 console.log(`[DEBUG] server will listen to: ${HOST}:${PORT}`)。) console.log(`[DEBUG] server will register with: ${AGENT_ID}`)。) const netServer = net.createServer((c) => { console.log(' [netServer] Client connected')。 c.on('data', (msg) =>/span> { console.log('[netServer] Received `message', MSG:', msg.toString() )。 }); c.on('end', () => { console.log('client disconnected')。 }); c.on('error', function (e) { console.log('Error: ' e.code) 。 }); c.write('hello ')。) c.pipe(c)。 }).listen({ host: HOST, port: PORT, family: 4, / ipv4, 與 python 的 socket.AF_INET 相同。 }); // Code copied from nodejs documentation page (does not make any difference) netServer.on('error', function (e) { console.log('Error: ' e.code) 。 if (e.code == 'EADDRINUSE'/span>) { console.log('Address in use, retrying...' )。 setTimeout(function () { netServer.close()。 netServer.listen(HOST, PORT) 。 }, 1000)。) } if ( e.code = 'ECONNRESET'/span> ){ console.log('Connection reset by peer...' )。 setTimeout(function () { netServer.close()。 netServer.listen(HOST, PORT) 。 }, 1000)。) } });客戶端:
/* 或者使用這個用node.js撰寫的tcp客戶端例子。 (起源于 示例代碼來自 http://www.hacksparrow.com/tcp-socket-programming-in-node-js.html。) */ var net = require('net')。 var HOST = 'localhost'; var PORT = 4243; var client = new net.Socket() 。 client.setTimeout(3000)。 client.connect(PORT, HOST, function() { console.log("Connected to " client.address()。 address " Source Port: " client.address().port " Family。" client.address().family)。) client.write('Hello, server! Love, Client。')。 }); client.on('data'/span>, function(data) { console.log('Received: ' data); client.end()。 }); client.on('error'/span>, function(e) { console.log('Error: ' e.code) 。 }); client.on('timeout', () => { console.log('socket timeout')。 client.end()。 }); client.on('close', function() { console.log('Connection closed')。 });最好的Hannes
uj5u.com熱心網友回復:
Steffen Ullrich說的完全正確。
在我的JavaScript代碼中,我正試圖創建一個服務器來監聽4243埠。
但是你不需要有一個服務器來監聽某個埠,你也可以用一個客戶端來監聽!(至少我是這樣想的。(至少我是這樣理解的)你可以按以下方式創建一個客戶端連接:
const netClient = net. createConnection(PORT, HOST, () => { console.log(' [netClient] Connected')。 }); netClient.on('data', (data) => /span> { console.log(' [netClient] Received data:', data. toString('utf8'))。) });通過 "client.on",那么你也可以接收資訊,就像它是一個服務器一樣。
我希望這對其他人來說是有用的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/311845.html標籤:
上一篇:選擇系統呼叫


