Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby IOread块在非阻塞插座上?_Ruby_Sockets_Nonblocking - Fatal编程技术网

Ruby IOread块在非阻塞插座上?

Ruby IOread块在非阻塞插座上?,ruby,sockets,nonblocking,Ruby,Sockets,Nonblocking,Ruby 1.8.7。我正在通过一个已打开并连接的套接字调用read: socket = Socket.new(AF_INET, SOCK_STREAM, 0) sockaddr = Socket.sockaddr_in(mp.port, mp.ip_address.ip) begin socket.connect_nonblock(sockaddr) [...] 通过调用select,然后再次连接以查找Errno::EISCONN来确认连接 然后,我再次调用select,超时为0,如果返

Ruby 1.8.7。我正在通过一个已打开并连接的套接字调用read:

socket = Socket.new(AF_INET, SOCK_STREAM, 0)
sockaddr = Socket.sockaddr_in(mp.port, mp.ip_address.ip)
begin
  socket.connect_nonblock(sockaddr)
[...]
通过调用select,然后再次连接以查找Errno::EISCONN来确认连接

然后,我再次调用select,超时为0,如果返回值不是nil,我将从套接字读取,首先确认它已设置O_NONBLOCK:

 rc = select([socket], nil, nil, 0)
 puts "  select returned: #{rc.pretty_inspect}"
 if rc
   begin
     puts "  reading: #{socket} nonblock: #{socket.fcntl(Fcntl::F_GETFL) & Fcntl::O_NONBLOCK}"
     response = socket.read
     puts "  done reading"
     [...]
这一切每分钟在一个循环中发生一次。第一次通过循环的输出为:

select returned: [[#<Socket:0xb6e0dcb8>], [], []]
reading: #<Socket:0xb6e0dcb8> nonblock: 2048
done reading
但是,第二次循环挂起在这里:

select returned: [[#<Socket:0xb6e0dcb8>], [], []]
reading: #<Socket:0xb6e0dcb8> nonblock: 2048
将gdb附加到进程会显示此回溯:

内核vsyscall中的0 0xFFFFFF410 从/lib/tls/i686/cmov/libc.so.6中选择1 0xb7e5539d 评估c:11020时rb_螺纹计划中的2 0x08064368 io_fread中的3 0x080785B

用对rcvfrom_nonblock的调用替换对read的调用是可行的,有趣的是,它没有得到EAGAIN,它实际上读取数据,正如您从select返回时所期望的那样

有什么想法吗


steve

您期望的答案是正确的,IOread不尊重在基础文件描述符上设置的标志:

请注意,此方法的行为类似于C中的fread函数 类似Read 2系统调用的行为,考虑Read Bead, 读取非块和系统读取

我很感激你用的是1.8,但是

你看到的过程卡在了io_fread,而且 IOread_非块也在1.8中提供。
我看不出在您的代码中,mp是在select2之后设置的。你确定它索引到的是同一个被标记为可读的套接字吗?很抱歉,这是在我简化问题代码时出现的一个错误。从剪切粘贴的输出中可以看出,它与gdb跟踪中的socket完全相同,在Ruby解释器中看起来就像一场竞赛。我同意。我有一半的期望答案是肯定的,IOread不尊重在底层文件描述符上设置的标志。也许这是预期的行为,但如果是这样的话,它应该被记录下来,因为它肯定不是人们所期望的。谢谢你的关注,Nikolai。还有一件事——因为堆栈显示了线程dispath——你有多个线程吗?其他线程是否有可能访问同一套接字?