【问题标题】:How to correctly handle partial write in Ruby Sockets?如何正确处理 Ruby 套接字中的部分写入?
【发布时间】:2011-10-26 06:58:47
【问题描述】:

TCP 套接字是流,而不是消息,因此某些系统上的 berkeley 套接字send() 函数可能发送的数据少于所需的数据。由于 Ruby Socket 是对 berkeley 套接字的非常薄的包装,AFAIK Socket#send 的行为与 berkeley 套接字 send() 完全相同。那么通过 Ruby TCP 套接字发送完整消息的正确方法是什么?在 python 中,它是一个名为sendall() 的特殊函数。但在 Ruby 中,我需要手动编写这样的代码:

while (sent = sock.send( data, 0 ) < data.length do
  data = data[ sent..-1 ]
end

【问题讨论】:

    标签: ruby sockets


    【解决方案1】:

    为了扩展 danielnegri 所说的内容,IO.write 最终在 io.c 中调用 io_binwrite

    ruby source 的相关位如下(nlen 最初设置为您的数据长度,offset 设置为 0)

    retry:
    arg.offset = offset; 
    arg.length = n;
    
    if (fptr->write_lock) {
      r = rb_mutex_synchronize(fptr->write_lock, io_binwrite_string, (VALUE)&arg);
    }
    else {
      long l = io_writable_length(fptr, n);
      r = rb_write_internal(fptr->fd, ptr+offset, l);
    }
    if (r == n) return len;
    if (0 <= r) {
      offset += r;
      n -= r;
      errno = EAGAIN;
    }
    if (rb_io_wait_writable(fptr->fd)) {
      rb_io_check_closed(fptr);
      if (offset < RSTRING_LEN(str))
        goto retry;
    }
    return -1L;
    

    如您所见,在写入所有数据之前,它将继续执行goto retry 并再次尝试。 rb_io_wait_writable 基本上检查 errno 的值是否应该再试一次(而不是更致命的事情),然后调用 select 以避免忙等待。

    【讨论】:

    • 非常感谢,正是我需要的。
    【解决方案2】:

    最近我使用了'write'方法:

    require "socket"  
    server = TCPServer.new('localhost', 20000)  
    loop do  
      Thread.start(server.accept) do |s|  
        print(s, " is accepted\n")  
        server.write(Time.now)  
        print(server, " is gone\n")  
        server.close  
      end  
    end
    

    试试:

    require 'socket'
    sock = Socket.open(Socket::PF_INET,Socket::SOCK_STREAM,Socket::IPPROTO_TCP)
    @data = "anyThing"
    @addr = pack_sockaddr_in(port, host)
    sock.connect(@addr)    #make the connection
    sock.send(@data, 0)
    

    您可能还想尝试使用 TCPSocket 类。我没有使用过任何这些 Ruby 代码,所以我不习惯这个特定的库;如果我弄错了,请告诉我。

    require 'socket'
    sock = TCPSocket.new(host, port)
    @data = "anyThing"
    sock.send(@data, 0) 
    

    【讨论】:

    • 是否有证据表明write 处理了部分发送?
    猜你喜欢
    • 1970-01-01
    • 2022-01-25
    • 2011-03-10
    • 2011-11-04
    • 2015-08-12
    • 2015-11-20
    • 1970-01-01
    • 1970-01-01
    • 2019-03-18
    相关资源
    最近更新 更多