ruby IO#读取非阻塞套接字上的块?

q5lcpyga  于 2023-05-17  发布在  Ruby
关注(0)|答案(1)|浏览(218)

Ruby 1.8.7.我在一个已经打开并连接的socket上调用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,我从socket读取,首先确认它设置了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 in __kernel_vsyscall()
1 0xb7e5539d in select()from /lib/tls/i686/cmov/libc.so.6
2 0x08064368 in rb_thread_schedule()at eval.c:11020
08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08 - 12 08
用对rcvfrom_nonblock的调用替换对read的调用可以工作,有趣的是,它并没有得到EAGAIN,它实际上是读取数据(正如您所期望的那样,从select返回)。

1sbrub3j

1sbrub3j1#

您期望得到的答案是正确的“IO#read does not respect the flags set on the underlying file descriptor”:
ruby 1.9.3 IO#read
请注意,此方法的行为类似于C中的fread()函数。如果你需要像read(2)系统调用这样的行为,可以考虑readpartial、read_nonblock和sysread。
我很感激你用了1.8但是

  • 你会看到进程卡在io_fread中,
  • IO#read_nonblock在1.8中也可用。

相关问题