2016-03-21 9 views
3

からのHTTP応答を送信しようとしているこれは私のコードです:私は、ブラウザ上で私のローカルIPを訪問するとき、私はは、低レベルのソケットサーバー

ERR_CONNECTION_RESET 

を言うエラーページを取得

# Process connections 

print('Listening on port', port) 
while True: 
    c, addr = s.accept() 
    print("Got connection from", addr) 
    msg = "<html></html>" 

    response_headers = { 
     'Content-Type': 'text/html; encoding=utf8', 
     'Content-Length': len(msg.encode(encoding="utf-8")), 
     'Connection': 'close', 
    } 

    response_headers_raw = ''.join('%s: %s\n' % (k, v) for k, v in response_headers.items()) 

    response_proto = 'HTTP/1.1' 
    response_status = '200' 
    response_status_text = 'OK' # this can be random 

    # sending all this stuff 
    r = '%s %s %s' % (response_proto, response_status, response_status_text) 
    c.send(r.encode(encoding="utf-8")) 
    c.send(response_headers_raw.encode(encoding="utf-8")) 
    c.send('\n'.encode(encoding="utf-8")) # to separate headers from body 
    c.send(msg.encode(encoding="utf-8")) 

    c.close() 

何私は間違っている?

注:

完全なコードスニペットはここにある:

import socket 

# Create socket object and set protocol 
s = socket.socket(
    socket.AF_INET, socket.SOCK_STREAM) 

# Get name of local machine 
host = socket.gethostname() 
port = 80 

# Bind 
s.bind((host, port)) 

# Listen and set backlog (?) 
s.listen(5) 

# Process connections 
print('Listening on port', port) 
while True: 
    c, addr = s.accept() 
    print("Got connection from", addr) 
    msg = "<html></html>" 

    response_headers = { 
     'Content-Type': 'text/html; encoding=utf8', 
     'Content-Length': len(msg.encode(encoding="utf-8")), 
     'Connection': 'close', 
    } 

    response_headers_raw = ''.join('%s: %s\n' % (k, v) for k, v in response_headers.items()) 

    response_proto = 'HTTP/1.1' 
    response_status = '200' 
    response_status_text = 'OK' # this can be random 

    # sending all this stuff 
    r = '%s %s %s' % (response_proto, response_status, response_status_text) 
    c.send(r.encode(encoding="utf-8")) 
    c.send(response_headers_raw.encode(encoding="utf-8")) 
    c.send('\n'.encode(encoding="utf-8")) # to separate headers from body 
    c.send(msg.encode(encoding="utf-8")) 

    c.close() 
+0

調査のためにChromeデベロッパーツールなどを使用しましたか? –

答えて

0

問題は、HTTPヘッダーはライン\r\nだけではなく\nによって分離する必要があるということです。 RFC 1945 - HTTP/1.0 Sec 2.2およびRFC 7230 - HTTP/1.1 Syntax and Routing Sec 3を参照してください。

これを変更すると、問題が解決されます。

import socket 

# Create socket object and set protocol 
s = socket.socket(
    socket.AF_INET, socket.SOCK_STREAM) 

# Get name of local machine 
host = "127.0.0.1" 
port = 8081 

# Bind 
s.bind((host, port)) 

# Listen and set backlog (?) 
s.listen(5) 

# Process connections 
print('Listening on port', port) 
while True: 
    c, addr = s.accept() 
    print("Got connection from", addr) 
    msg = "<html><body><h1>This is a test</h1><p>More content here</p></body></html>" 

    response_headers = { 
     'Content-Type': 'text/html; encoding=utf8', 
     'Content-Length': len(msg), 
     'Connection': 'close', 
    } 

    response_headers_raw = ''.join('%s: %s\r\n' % (k, v) for k, v in response_headers.items()) 

    response_proto = 'HTTP/1.1' 
    response_status = '200' 
    response_status_text = 'OK' # this can be random 

    # sending all this stuff 
    r = '%s %s %s\r\n' % (response_proto, response_status, response_status_text) 
    c.send(r) 
    c.send(response_headers_raw) 
    c.send('\r\n') # to separate headers from body 
    c.send(msg.encode(encoding="utf-8")) 

    c.close() 
+0

私の理解では、CRLF '( '\ r \ n')'はウィンドウ固有のフォーマットです。これはUnixシステム上で動作しますか? – dopatraman

+0

また、この解決策は機能しません。私は接続を受けることができますが、ブラウザに応答を送ることはできません。 – dopatraman

+0

はい、CRLFはHTTPによってエンドオブラインマーカーとして使用されます([RFC 7230](https://tools.ietf.org/html/rfc7230#section-3)参照)。あなたのコードを実行すると、私は接続リセットを取得します。各ヘッダー行の間で '\ r \ n 'を使うように変更したときに動作します。フルコードで解答を編集しました。 – drew010

0

エラーERR_CONNECTION_RESETによると、あなたのTCPソケットはポートを正常に受信しない可能性があります。

コードでポートを8080に変更し、出力にHello worldを書き込むと、正しいHTMLページが得られます。あなたが成功した80ポートを聞きたい場合は

、あなたのPythonスクリプトを実行するには、rootユーザー権限を使用する必要があります。

80ポートがシステムであるためである `sudoのパイソンserver.py」

制限付きポート:Why are the first 1024 ports restricted to the root user only?

+0

もし 'bind'を聞いていなければ、クライアントは接続を拒否するか、結局はタイムアウトになります。しかし、リセットはありません。それはある時点で接続していたことを示しています。 – drew010

+0

@ drew010に追加するだけで、コマンドライン経由でポート80で稼働しているサーバーにアクセスできます。そのポートでの接続は問題ではありません。 – dopatraman

-1

私はあなたがポート80を聞いて接続を受け入れることができると仮定します。そうしないと、サーバーは早期に例外をスローする必要があるからです。

あなたのサーバーはクライアントの要求を読み込まず、代わりにいくつかのデータを送信し、クライアントからの要求をソケットバッファに残して接続を閉じるため、接続がリセットされると思います。これは、すでに尋ねられており、Perl: Connection reset with simple HTTP serverおよびHTTP Server Not Sending Complete File To WGET, Firefox. Connection reset by peer?および"The connection was reset" on web browsers when trying to connect to a localhost socket serverおよびUltra simple HTTP socket server, written in PHP, behaving unexpectedlyおよびSimple http generic server using fork and dupで回答された典型的なエラーです。

+0

これらのリンクのどれも、実際に問題を解決する方法を詳しく説明していません。 – dopatraman

+0

@dopatraman:問題は、クライアントからの要求を読み取っておらず、レスポンスを送信して未読データでソケットを閉じるということです。解決策は明らかにクライアントからの要求を実際に読み取ることです。この相関関係を理解し​​ていないか、リクエストを読む方法が分かりませんでしたか? –

関連する問題