2017-01-26 4 views
0

私はUnixシステムプログラミングに夢中になり、現在ソケットで最小限のhttpサーバを実装しようとしています。最小限のソケットhttpサーバ

現在、私は私が127.0を訪問したときに、ブラウザで何かを受け取るためにソケットをクローズしなければならないのはなぜ次のコード(それはocamlのだ、流れはどの言語でも同じです)

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 

を持っています。 0.1:8888?最後の行のソケットを閉じなければ、私のブラウザは永遠に回転し続けます。 ソケットの反対側に何かを送ることはできませんか?ソケットを閉じないと、ブラウザに何も表示されないのはなぜですか?

答えて

1

あなたが適切にHTTP/1.1を処理するために行う必要がある3つの大きなもの(少なくとも)があります

1)ブラウザの要求は、単一のパケットに到着しない場合がありますので、あなたは、入力をバッファリングする必要がありますが。これは、Unix.recvコールが部分的な要求を受信し、次のコールが残りの要求(または次のチャンク)を取得することを意味します。最も簡単な方法は、ストリームを何らかの種類のリーダーでラップすることです。これにより、ライン全体を同期して要求することができます。

2)応答を送信するときは、Content-Lengthヘッダーを指定する必要があります。これがなければ、ブラウザはデータがいつ終了したかを知ることができず、それがなければ、ブラウザは応答が完了したことと接続が予期せず閉じられたことの違いを知ることができません。

3)HTTP 1.1では、サーバーがクライアントに明示的に指示しない限り、接続は永続的であるとみなされます。 Connection: keep-aliveをサポートすると、サーバーのパフォーマンスは向上しますが、最小限の実装では、少なくともConnection: closeの応答ヘッダーを送信する必要があります。

関連する問題