2012-11-23 14 views
5

Mam 2 Część pytanie na odczyt z gniazd i jak to udało się na serwerach, takich jak Ruby Unicorn lub MongrelaJak czytać z gniazda tcpserver w ruby ​​użyciem należy przeczytać, readpartial i read_nonblock

  1. Nauczyłem to, że odczyt z gniazda różni się od odczytu pliku i że nie ma wyraźnego komunikatu EOF wysłanego, a dane są strumieniem nieskończonym. Skąd wiesz, kiedy przestać czytać? Mój TCPServer na przykład w tym przypadku, kiedy trafiłem na mój serwer, uzyskując dostęp do http://localhost:9799 z przeglądarki, zawiesza się, gdy nie ma już danych do odczytania i nie rzuci również EOFError.
 

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 
 

Chciałbym wiedzieć, co w praktyce/standardowe podejście najlepiej wykorzystywane przez serwery Ruby. Widzę, że Unicorn używa read_nonblock z biblioteki kgio, a kundel używa readpartial (nie jestem pewien co do nich, ale przechodzę przez kod, to jest to, co uważam za przyjęte podejście.) Nawet przy sprawdzaniu \ r \ n jak serwer wie wejście jest kompletne. Czy można wyjaśnić, jak to zrobić (i myślę, że gets nie jest podejście - jego z read, readpartial, read_nonblock).

2). Byłbym wdzięczny za kilka wskazówek, jak to osiągnąć w serwerach takich jak jednorożec czy pasażer.

Dziękuję.

Odpowiedz

5

Zrobione w jednorożec tutaj https://github.com/defunkt/unicorn/blob/master/lib/unicorn/http_request.rb#L69-L71

Jest add_parse metoda (przeczytaj komentarze powyższych metod) https://github.com/defunkt/unicorn/blob/master/ext/unicorn_http/unicorn_http.rl#L760-L778

wziąć również spojrzeć na niektóre wyjaśnienia tutaj http://www.ruby-forum.com/topic/2267632#1014288

Oto twój kod roboczych przy użyciu 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

Dziękuję za odpowiedź i wprowadzenie mnie do http_parser.rb. Znasz serwery, które nie używają biblioteki parserów i wybierają inne podejście? – Sid

+0

Nie znam serwerów, które nie używają analizatorów składowych, jakie inne podejście? – Shtirlic

+0

Przykro mi, co mam na myśli, to serwery, które nie korzystają z biblioteki http_parser.rb. – Sid

Powiązane problemy