Ruby on Rails TCPSocket在客户端应用程序中冻结,而循环使用gets

时间:2012-06-06 13:41:38

标签: c# ruby-on-rails sockets

我正在关注教程:http://www.tutorialspoint.com/ruby/ruby_socket_programming.htm并使用它来设置"简单客户端"。

代码如下:

    require 'socket'      # Sockets are in standard library

    hostname = 'localhost'
    port = 2000

    s = TCPSocket.open(host, port)

    while line = s.gets   # Read lines from the socket
      puts line.chop      # And print with platform line terminator
    end
    s.close               # Close the socket when done

当我执行单个s.gets语句时,我从服务器获得第一个响应行。当我再次执行s.gets时,我会得到第二个响应行,等等。但是,当我到达响应结束并执行s.gets时,程序将进入冻结状态。 (这是我从Rails控制台测试上面的程序)。当我运行代码时会发生同样的情况 - 当while语句执行最终的s.gets时会发生冻结。关于如何解决这个问题的任何想法?

有关信息:服务器是一个C#服务器,它使用以下C#代码发送响应消息(响应的每一行使用相同的代码,并且响应中的最后一行与其他行的处理方式不同): / p>

    socket.Send(Encoding.ASCII.GetBytes(msg + "\r\n"));

所以我认为客户端冻结,因为它可能无法解释服务器"响应结束"正常。有什么想法吗?

4 个答案:

答案 0 :(得分:2)

从套接字读取nil值似乎有问题。仍然不确定为什么会发生这种情况,但使用Recovering from a broken TCP socket in Ruby when in gets()中建议的选择器可以非常好地解决问题(可能会提出他的答案,但没有足够的代表)。

我遵循的解决方案是在方法中添加选择器,如下所示:

    def next_line_readable?(socket)
      readfds, writefds, exceptfds = select([socket], nil, nil, 0.1)
      p :r => readfds, :w => writefds, :e => exceptfds
      readfds #Will be nil if next line cannot be read
    end

然后在主程序中使用它:

    socket = TCPSocket.open(host, port)
    while next_line_readable?(socket)
      puts socket.gets.chop
    end

答案 1 :(得分:0)

尝试使用socket.readsocket.recvfrom方法代替socket.gets

这是一样的行为吗?

答案 2 :(得分:0)

试试这个在ruby中编写tcp客户端和服务器

def sendto(str)
  begin
     socket.write(str)
    puts "Sent Message to:" +  socket.peeraddr[2]
  rescue Exception=>e
    puts red("Error Make sure the target is connected")
  end
end

检查出来是完美的,直到4小时然后断开连接 Connection to ruby based server

答案 3 :(得分:0)

使用recv代替获取

   server = TCPServer.new 53492 # Server bound to port 53492
    loop do
      client = server.accept
      ansiString = client.recv(100).chomp
      client.puts result
      client.close
     end

您也可以将其转换为线程:

   server = TCPServer.new 53492 # Server bound to port 53492
   Thread.start(server.accept) do |client|
      loop do
        client = server.accept
        ansiString = client.recv(100).chomp
        client.puts result
        client.close
      end
    end