7

我正在读取 TCP 套接字上的输入行,类似于:

class Bla  
  def getcmd
    @sock.gets unless @sock.closed?
  end

  def start     
    srv = TCPServer.new(5000)
    @sock = srv.accept
    while ! @sock.closed?
      ans = getcmd
    end
  end
end

如果端点在 getline() 运行时终止连接,则 gets() 挂起。

我该如何解决这个问题?是否有必要进行非阻塞或定时 I/O?

4

5 回答 5

7

您可以使用 select 查看是否可以安全地从套接字获取,请参阅使用此技术的 TCPServer 的以下实现。

require 'socket'

host, port = 'localhost', 7000

TCPServer.open(host, port) do |server|
  while client = server.accept
    readfds = true
    got = nil
    begin
      readfds, writefds, exceptfds = select([client], nil, nil, 0.1)
      p :r => readfds, :w => writefds, :e => exceptfds

      if readfds
        got = client.gets 
        p got
      end
    end while got
  end
end

这里有一个试图破坏服务器的客户端:

require 'socket'

host, port = 'localhost', 7000

TCPSocket.open(host, port) do |socket|
  socket.puts "Hey there"
  socket.write 'he'
  socket.flush
  socket.close
end
于 2008-09-15T16:13:31.390 回答
2

IO#关闭?当读取器和写入器都关闭时返回 true。在您的情况下,@sock.gets 返回 nil,然后您再次调用 getcmd,这将在一个永无止境的循环中运行。您可以使用 select,也可以在 get 返回 nil 时关闭套接字。

于 2008-09-18T12:54:45.773 回答
0

我建议使用 readpartial 从您的套接字中读取数据并捕获对等重置:

while true
    sockets_ready = select(@sockets, nil, nil, nil)
    if sockets_ready != nil
      sockets_ready[0].each do |socket|
        begin
          if (socket == @server_socket)
            # puts "Connection accepted!"
            @sockets << @server_socket.accept
          else
            # Received something on a client socket
            if socket.eof?
              # puts "Disconnect!"
              socket.close
              @sockets.delete(socket)
            else
              data = ""
              recv_length = 256
              while (tmp = socket.readpartial(recv_length))
                data += tmp
                break if (!socket.ready?)
              end
              listen socket, data
            end
          end
        rescue Exception => exception
          case exception
            when Errno::ECONNRESET,Errno::ECONNABORTED,Errno::ETIMEDOUT
              # puts "Socket: #{exception.class}"
              @sockets.delete(socket)
            else
              raise exception
          end
        end
      end
    end
  end

这段代码大量借鉴了 M. Tim Jones 的一些不错的 IBM 代码。请注意,@server_socket 由以下方式初始化:

@server_socket = TCPServer.open(port)

@sockets 只是一个套接字数组。

于 2011-05-15T00:56:04.103 回答
0

我只是 pgrep "ruby" 来查找 pid,然后杀死 -9 pid 并重新启动。

于 2016-03-18T04:55:03.977 回答
-2

如果您相信 ruby​​ 套接字的rdoc,它们不会实现gets. 这让我相信 get 是由更高级别的抽象(可能是 IO 库?)提供的,并且可能不知道特定于套接字的事情,例如“连接关闭”。

尝试使用recvfrom而不是gets

于 2008-09-14T23:51:04.357 回答