Ruby 带有 Node.js 客户端的 UNIXServer

Ruby UNIXServer with Node.js client

我有这个使用 Unix 套接字的 Ruby 服务器:

require 'socket'

server = UNIXServer.new('/tmp/ciccio.sock')
loop do
  sock = server.accept
  loop do
    begin
      data = sock.recv(1024)
      data = "DO SOMETHING -> #{data}"
      sock.write(data)
      sock.flush
    rescue Errno::EPIPE, Errno::ENOTCONN
      break
    end
  end
end

我在 JavaScript 中有这个客户端,它使用 node.js net api:

Net = require('net');

var client = Net.connect({path: '/tmp/ciccio.sock'}, () => {
  console.log('write data');
  client.write('hello world!');
});

client.on('data', (data) => {
  console.log(data.toString());
  client.end();
});

client.on('end', () => {
  console.log('end');
});

client.on('error', (error) => {
  console.log(error.toString());
});

问题是在服务器循环的第一次迭代中,recv 接收到正确的字符串并且服务器用字符串 data 回复客户端。但是在第二次迭代时 recv 接收到空数据,因此无限循环开始......服务器继续接收空数据并且 recv 不阻塞......

如果我像这样使用 ruby 客户端一切正常...

require 'socket'

sock = UNIXSocket.new('/tmp/ciccio.sock')
loop do
  sock.write('hello world!')
  data = sock.recv(1024)
  puts data
  sleep(10)
end
sock.close

您的客户端在连接后关闭连接,写入 "hello world",然后收到响应。现在您的服务器正在一个已关闭的套接字上调用 recv,这将 return 一个空字符串。由于您无限期地循环读取此套接字,因此它永远不会 return 控制回外循环为第二个客户端调用 accept。 ruby 版本的客户端可以正常工作,因为它从不关闭与服务器的连接。

在收到一个空字符串后跳出你的内部循环应该会得到你想要的,

require 'socket'

server = UNIXServer.new('/tmp/ciccio.sock')
loop do
  sock = server.accept
  loop do
    begin
      data = sock.recv(1024)
      break if data.empty?

      data = "DO SOMETHING -> #{data}"
      sock.write(data)
      sock.flush
    rescue Errno::EPIPE, Errno::ENOTCONN
      break
    end
  end
end

另一个潜在的问题是您的服务器只能为单个客户端的单个连接提供服务,因为内部循环会阻止对 accept 的任何后续调用,直到当前连接结束。