【发布时间】: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上调用它吗? -
@mudasobwa 我使用了文档nodejs.org/api/net.html#net_net_connect_options_connectlistener的示例
-
问题是recv不会阻塞,所以它只能返回那个瞬间可用的东西,有时什么都没有。 W. Richard Stevens 是这方面的权威。读他的书
-
@JohnLaRooy
recv是阻塞调用,而recv_nonblock是非阻塞变体。当然,这假设文件描述符在调用recv之前没有设置为O_NONBLOCK。我敢打赌,情况并非如此,recv正在阻塞,但在连接完成后,recv正在关闭的套接字上被调用,因此将始终返回一个空字符串。
标签: ruby node.js sockets client-server unix-socket