红宝石 1.8.7。我正在调用已打开并连接的套接字上的读取:
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 附加到进程显示此回溯:
0 0xffffe410 在 __kernel_vsyscall ()
1 0xb7e5539d in select () from /lib/tls/i686/cmov/libc.so.6
2 0x08064368 in rb_thread_schedule () 在 eval.c:11020
3 0x080785bb in io_fread (
用对 rcvfrom_nonblock 的调用替换对 read 的调用是有效的,有趣的是它没有获得 EAGAIN,它实际上读取数据(正如您所期望的那样从 select 返回)。
你期待答案“IO#read 不尊重底层文件描述符上设置的标志”是正确的:
请注意,此方法的行为类似于 C 中的 fread() 函数。如果您需要 类似 read(2) 系统调用的行为,考虑 readpartial, read_nonblock 和 sysread.
感谢您使用 1.8,但是
io_fread
,并且IO#read_nonblock
也在 1.8 中可用。