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来确认连接.
然后我再次使用0超时调用select,如果返回值不为n,则从套接字读取,首先确认它已设置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附加到进程会显示此回溯:
__kernel_vsyscall()中的0 0xffffe410
来自/lib/tls/i686/cmov/libc.so.6的select()中的1 0xb7e5539d
2 0x08064368在rb_thread_schedule()中的eval.c:11020
io_fread中的3 0x080785bb(
通过调用rcvfrom_nonblock替换要读取的调用有效,有趣的是它没有获得EAGAIN,它实际上读取数据(正如您所期望的那样,从select返回).
有任何想法吗?
史蒂夫
最佳答案 你是正确的期望答案“IO#read不尊重底层文件描述符上设置的标志”:
Note that this method behaves like fread() function in C. If you need
the behavior like read(2) system call, consider readpartial,
read_nonblock and sysread.
我很欣赏你使用1.8,但是
>你看到这个过程陷入了io_fread,并且
> IO#read_nonblock也可用于1.8.