2012-11-23 12 views
5

Ich habe einen 2 Teil Frage beim Lesen von Sockets und wie ist es geschafft, auf Ruby-Servern wie Unicorn oder MischlingsWie aus einer TCPServer Steckdose in rubin ausgelesen, readpartial und read_nonblock

  1. ich gelernt habe gelesen Das Lesen von einem Socket unterscheidet sich von dem Lesen einer Datei, und es wird keine eindeutige EOF-Nachricht gesendet, und die Daten sind ein endloser Strom. Woher weißt du, wann du aufhören sollst? Mein TCPServer zum Beispiel in diesem Fall, wenn ich meinen Server durch Zugriff auf http://localhost:9799 von einem Browser getroffen habe, hängt es, nachdem es keine Daten mehr zu lesen gibt und es den EOFError auch nicht werfen wird.
 

require 'socket' 

READ_CHUNK = 1024 
socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM) 
addr = Socket.pack_sockaddr_in(9799, '127.0.0.1') 
socket.bind(addr) 
socket.listen(Socket::SOMAXCONN) 
socket.setsockopt(:SOCKET, :REUSEADDR, true) 

puts "Server is listening on port = 9799" 
loop do 
    connection, addr_info = socket.accept 
    data_buffer = "" 

    loop do 
     begin 
      connection.read_nonblock(READ_CHUNK, data_buffer) 
      puts "Buffer = #{data_buffer}" 
     rescue Errno::EAGAIN => e 
      IO.select([connection])   
      retry 
     rescue EOFError 
      break 
     end 
    end 
    connection.write("HTTP/1.1 200 \r\n") 
    connection.write("Content-Type: text/html\r\n") 
    connection.write("Status 200 \r\n") 
    connection.write("Connection: close \r\n") 
    connection.write("Hello World \r\n") 
    connection.close 
end 
 

Ich würde gerne wissen, was ist die beste Praxis/Standard-Ansatz von Ruby-Servern. Ich sehe das Unicorn verwendet read_nonblock von kgio Bibliothek und Mongrel verwendet readpartial (Ich bin nicht sicher über diese, aber durch den Code geht das ist, was ich fühle, ist der Ansatz angenommen.) Auch mit Prüfungen für \ r \ n wie weiß der Server Die Eingabe ist abgeschlossen. Könnte erklären, wie dies getan werden sollte (und ich denke, gets ist nicht der Ansatz - es mit read, readpartial, read_nonblock).

2). Ich würde wirklich ein paar Zeilen darüber schätzen, wie dies in Servern wie Einhorn oder Beifahrer erreicht wird

Vielen Dank.

Antwort

5

Es ist in Einhorn hier getan https://github.com/defunkt/unicorn/blob/master/lib/unicorn/http_request.rb#L69-L71

add_parse Methode (lesen Sie die Kommentare über Methoden) Es https://github.com/defunkt/unicorn/blob/master/ext/unicorn_http/unicorn_http.rl#L760-L778 ist

Werfen Sie auch einen Blick auf einige Erklärungen hier http://www.ruby-forum.com/topic/2267632#1014288

Hier ist Ihre Arbeitscode mit http_parser.rb https://gist.github.com/4136962

gem install http_parser.rb

require 'socket' 
require "http/parser" 


READ_CHUNK = 1024 * 4 
socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM) 
addr = Socket.pack_sockaddr_in(9799, '127.0.0.1') 
socket.bind(addr) 
socket.listen(Socket::SOMAXCONN) 
socket.setsockopt(:SOCKET, :REUSEADDR, true) 

puts "Server is listening on port = 9799" 
loop do 
    connection, addr_info = socket.accept 

    parser = Http::Parser.new 
    begin 
     data = connection.readpartial(READ_CHUNK) 
     puts "Buffer = #{data}" 
     parser << data 
    end until parser.headers 

    connection.write("HTTP/1.1 200 \r\n") 
    connection.write("Content-Type: text/html\r\n") 
    connection.write("Status 200 \r\n") 
    connection.write("Connection: close \r\n") 
    connection.write("\r\n\r\n") 
    connection.write("Hello World \r\n") 
    connection.close 
end 
+0

Vielen Dank für Ihre Antwort und Einführung in http_parser.rb. Kennen Sie irgendwelche Server, die die Parser-Bibliothek nicht verwenden und sich für einen anderen Ansatz entscheiden? – Sid

+0

Ich kenne keine Server, die keine Parser verwenden, welche Art von einem anderen Ansatz? – Shtirlic

+0

Es tut mir leid, was ich meinte, war Server, die die Bibliothek http_parser.rb nicht verwenden. – Sid