2016-12-01 11 views
1

私はPythonでHTTPプロキシを作成していますが、私のプロキシはWebサーバーの応答のみを受け付け、ブラウザの次の要求とデータ転送を完全に無視するという点で問題がありますちょうど停止します。ここでは、コードです:プロキシサーバーがすべてのデータを送信していないpython

import socket 

s = socket.socket() 
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 

bhost = '192.168.1.115' 
port = 8080 
s.bind((bhost, port)) 
s.listen(5) 

def server(sock, data, host): 
    p = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    p.connect((host, 80)) 
    p.send(data) 
    rdata = p.recv(1024) 
    print(rdata) 
    sock.send(rdata) 


    while True: 
     sock, addr = s.accept() 
     data = sock.recv(1024) 
     host = data.splitlines()[1][6:] 
     server(sock, data, host)` 

+1

このフォーマットは、 'server()'の内部で受け入れている接続と 'server()'をもう一度呼び出すため、変です。それは意図的なのでしょうか? –

答えて

1

は、残念ながら、私は本当にしないでください:-)私は14だと学ぶために多く持っているように、これは単に試用版とヘルプははるかに高く評価されているコードについては申し訳ありませんあなたのコードがどのように機能すべきかを見てください。ここでは、単純なHTTPプロキシのように見えますか? 基本的なプロキシサーバーではどうすればよいですか:

  1. クライアントからの接続を受け入れ、HTTP要求を受け取ります。
  2. リクエストを解析し、その宛先を抽出します。
  3. フォワード要求と応答。
  4. (オプション)サポートConnection: keep-alive

非常に単純化されたコードをステップバイステップで作成してみましょう。

プロキシはどのようにクライアントを受け入れますか。ソケットが作成され、パッシブモードに移動する必要があります。

import socket, select 
sock = socket.socket() 
sock.bind((your_ip, port)) 
sock.listen() 
while True: 
    client_sock = sock.accept() 
    do_stuff(client_sock) 

TCPコネクションが確立されると、それは要求を受ける時間です。我々はこのような何かを取得しようとしていると仮定しましょう:TCPでは

GET /?a=1&b=2 HTTP/1.1 
Host: localhost  
User-Agent: my browser details 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8  
Accept-Language: en-gb,en;q=0.5  
Accept-Encoding: gzip, deflate  
Connection: keep-alive 

を、メッセージの境界は保持されませんので、我々は(GETリクエスト用)は、少なくとも最初の2行を取得するまで、我々は知っているために待たなければなりません何後で行うには:我々は、リモートホスト名を持ってたら、それは要求と応答を転送するための時間

def do_stuff(sock): 
    data = receive_two_lines(sock) 
    remote_host = parse_request(data) 

です:

def do_stuff(client_sock): 
    data = receive_two_lines(client_sock) 
    remote_host = parse_request(data) 
    remote_ip = socket.getaddrinfo(remote_host) # see the docs for exact use 

    webserver = socket.socket() 
    webserver.connect((remote_ip, 80)) 

    webserver.sendall(data) 
    while it_makes_sense(): 
     client_ready = select.select([client_sock], [], [])[0] 
     web_ready = select.select([webserver], [], [])[0] 

     if client_ready: 
      webserver.sendall(client_sock.recv(1024)) 
     if web_ready: 
      client_sock.sendall(webserver.recv(1024)) 

selectに注意してください - これがあれば、我々が知っている方法ですリモートピアが私たちにデータを送ってきました。再び、メッセージの境界はTCPに保存されていないので、

  1. チャンスは、あなたが単一client_sock.recv(1024)呼び出しで、いくつかのGETリクエストを取得します:私は実行して、このコードをテストして行うには、左のものがありませんでした。おそらく、データを受け取るたびに追加のリクエストを調べるでしょう。
  2. リクエストは、POST、HEAD、PUT、DELETE、およびその他のタイプのリクエストで異なる場合があります。それに応じて解析します。
  3. ブラウザとサーバーは通常、ヘッダーにConnection: keep-aliveオプションを設定することで1つのTCP接続を利用しますが、ドロップすることもできます。リモートピアによって閉じられた切断とソケットを検出する準備ができている(簡単に言うと、これはwhile it_makes_sense()と呼ばれています)。
  4. bindlistenacceptrecvsendsendallgetaddrinfoselect - これらすべての機能が例外をスローすることができます。それを捕らえてそれに応じて行動するほうがよい。
  5. コードは現在、一度に1つのサーバーになります。
+0

ありがとうVovanrock2002それは本当に私を助けてくれました:-) –

+0

私は自分のコードを計画していました。接続を受け入れてHTTPリクエストを受け取り、ホストを見つけてそれをホストに渡し、ホストに接続してブラウザからHTTPリクエストを送信し、レスポンスを受け取り、ブラウザ、そしてこれのすべてがただのループになるようにします。 –

関連する問題