2008-09-14 64 views
7

我讀的輸入線路上的TCP套接字,與此類似:從紅寶石破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?

回答

-2

如果您認爲rdoc爲紅寶石套接字,則它們不會執行gets。這導致我相信獲取是由更高層次的抽象(也許是IO庫?)提供的,並且可能不知道「連接已關閉」等特定於套接字的事物。

嘗試使用recvfrom代替gets

6

您可以使用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 
+0

在那裏小錯字,我相信你想要的東西:http://gist.github.com/527750 – rogerdpack 2010-08-16 21:14:08

2

的IO#關閉?讀寫器關閉時返回true。 在你的情況下,@ sock.gets返回nil,然後你再次調用getcmd,並且運行在一個永無止境的循環中。您可以使用select,或者在返回nil時關閉套接字。

+0

如果關閉套接字的獲得將掛起 – QueueHammer 2009-12-29 15:54:07

+0

是的,如果您在getcmd循環中添加打印「這裏」 聲明你會發現它永遠循環着,閱讀「」 – rogerdpack 2010-08-16 21:14:39

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 

這個代碼在很大程度上借鑑了一些nice IBM code由M.蒂姆·瓊斯借用。請注意,@server_socket的初始化爲:

@server_socket = TCPServer.open(port) 

@sockets只是一個套接字數組。

0

我只是用pgrep「ruby」找到pid,並殺死-9的pid並重啓。