【问题标题】:Ruby UNIXServer with Node.js client带有 Node.js 客户端的 Ruby UNIXServer
【发布时间】:2015-11-25 12:52:04
【问题描述】:

我有这个使用 Unix Socket 的 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

我有这个使用 node.js net api 的 JavaScript 客户端:

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

【问题讨论】:

  • 你为什么要在data上打电话给client.end();?不应该在end 上调用它吗?
  • 问题是recv不会阻塞,所以它只能返回那个瞬间可用的东西,有时什么都没有。 W. Richard Stevens 是这方面的权威。读他的书
  • @JohnLaRooy recv 是阻塞调用,而 recv_nonblock 是非阻塞变体。当然,这假设文件描述符在调用recv 之前没有设置为O_NONBLOCK。我敢打赌,情况并非如此,recv 正在阻塞,但在连接完成后,recv 正在关闭的套接字上被调用,因此将始终返回一个空字符串。

标签: ruby node.js sockets client-server unix-socket


【解决方案1】:

您的客户端在连接后关闭连接,写入"hello world",然后收到响应。现在您的服务器正在一个已关闭的套接字上调用recv,这将返回一个空字符串。由于您无限期地循环读取此套接字,因此它永远不会将控制权返回到外部循环以调用 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 的任何后续调用,直到当前连接结束。

【讨论】:

  • “现在您的服务器正在一个已关闭的套接字上调用 recv,这将返回一个空字符串”:这是我不明白的部分。谢谢!
猜你喜欢
  • 2011-11-12
  • 1970-01-01
  • 2013-01-28
  • 1970-01-01
  • 2012-04-19
  • 1970-01-01
  • 2012-03-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多