Ruby IOread块在非阻塞插座上?
Ruby 1.8.7。我正在通过一个已打开并连接的套接字调用read: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,如果返
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——你有多个线程吗?其他线程是否有可能访问同一套接字?