2017-01-26 2 views
0

Ich bekomme meine Füße nass mit Unix-System-Programmierung, und versuche derzeit, eine minimale HTTP-Server mit Sockets zu implementieren.Minimal Socket http Server

Zur Zeit habe ich den folgenden Code (es ocaml ist, geht der Ablauf ist der gleiche wie in jeder Sprache)

let establish_server() = 
    let socket = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in 
    Unix.bind socket (Unix.ADDR_INET ((Unix.inet_addr_of_string "127.0.0.1"), 8888)); 
    Unix.listen socket 128; 
    print_endline "accepting now"; 
    while true do 
    let (service_socket, addr) = Unix.accept socket in 
    print_endline "Something arrived!"; 
    let b = Bytes.create 1024 in 
    let _ = Unix.recv service_socket b 0 1024 [Unix.MSG_PEEK] in 
    print_endline @@ Bytes.to_string b; 
    let response = Bytes.of_string "HTTP/1.1 200 OK\n\nHey from Ocaml!" in 
    let _ = Unix.send service_socket response 0 (Bytes.length response) [Unix.MSG_PEEK] in 
    Unix.close service_socket; 
    done 

Warum muss ich den Socket schließen etwas im Browser zu erhalten, wenn ich 127,0 besuchen. 0.1: 8888? Wenn ich den Socket in der letzten Zeile nicht schließe, dreht sich mein Browser für immer weiter. Kannst du nicht einfach etwas ans andere Ende der Steckdose schicken? Warum zeigt der Browser nichts an, wenn ich den Socket nicht schließe?

Antwort

1

Es gibt (mindestens) drei große Dinge, die Sie tun müssen, um HTTP zu Handling/1.1 richtig:

1) Sie müssen Eingang in den Puffer, da die Anforderung des Browsers nicht in einem einzigen Paket ankommen könnten. Dies bedeutet, dass der Anruf Unix.recv eine teilweise Anfrage empfangen kann, und der nächste Anruf wird den Rest der Anfrage (oder den nächsten Chunk) abrufen. Der einfachste Ansatz besteht darin, den Stream in eine Art Lesegerät einzubinden, mit dem Sie eine gesamte Zeile synchron anfordern können.

2) Wenn Sie eine Antwort senden, müssen Sie eine Content-Length Kopfzeile angeben. Ohne dies weiß der Browser nicht, wann die Daten fertig sind - und ohne diesen kann der Browser nicht unterscheiden, ob die Antwort abgeschlossen ist und die Verbindung unerwartet geschlossen wurde.

3) In HTTP 1.1 werden Verbindungen als persistent angenommen, es sei denn, der Server teilt dem Client explizit mit, dass dies nicht der Fall ist. Ihr Server wird besser funktionieren, wenn Sie Connection: keep-alive unterstützen, aber für eine minimalistische Implementierung sollten Sie mindestens einen Antwort-Header Connection: close senden.