Golangで書かれたWebサーバーでHTTP/1.1のkeep-aliveを検証する
HTTP/1.1にはKeep-Aliveという通信方法があります。HTTP/1.0の頃は1セットの通信が終わるたびに接続・切断処理が入っていたので非効率だったため、複数のリクエストが来た場合にコネクションを使い回す機能になります。 今回はGolangで書かれたサーバーを実行してWiresharkで通信の様子をキャプチャしています
コード
keep-aliveの実装コードの一部です。Requestを終わりまで読み取り、コネクションを再利用します。
//Accept後のソケットでなんども応答を返すためにループ for { //タイムアウトを設定 conn.SetReadDeadline(time.Now().Add(5 * time.Second)) //リクエストを読み込む request, err := http.ReadRequest(bufio.NewReader(conn)) if err != nil { //タイムアウトもしくはソケットクローズ時は終了 //それ以外はエラーにする neterr, ok := err.(net.Error) //ダウンキャスト if ok && neterr.Timeout() { fmt.Println("timeout") break } else if err == io.EOF { break } panic(err) } //リクエストを表示 dump, err := httputil.DumpRequest(request, true) if err != nil { panic(err) } fmt.Println(string(dump)) content := "Hello World\n" //レスポンスを書き込む //HTTP/1.1かつ,ContentLengthの設定が必要 response := http.Response{ StatusCode: 200, ProtoMajor: 1, ProtoMinor: 1, ContentLength: int64(len(content)), Body: ioutil.NopCloser( strings.NewReader(content)), } response.Write(conn) }
通信内容
curlで2回リクエストを投げています。成功すると2回hello world
が帰ってきます
$ curl localhost:8888 localhost:8888 hello world hello world
キャプチャ結果
続いてWiresharkのキャプチャ結果を貼りますちょっと分かり辛いかもしれませんが、
keep aliveが無い方は2回のリクエストに対してそれぞれ接続、切断処理を行なっていますが、keep aliveがある方はコネクションを使いまわして全部で1度しか接続、切断処理をしていないことがわかります。