2017-04-10 4 views
0

私はソケットを初めて使用しています。私は単純な「プロキシ」サーバーをPythonで書いています。このサーバーはリモートサーバーからデータを取得してクライアント(ブラウザ)に送信します。私は思っていた:time.sleepなしでresponse_textを送信する方法はありますか?私はtime.sleep(0.5)を削除しようとしていますが、私は 'Content-lenght'がパッケージの長さと等しくないように、リモートサーバから1つのデータパッケージを取得するだけで、エラーが出ます(私はrecv() buffer_sizeに等しいサイズのバッファです。したがって、サーバーデータに1つの4096バイトのパッケージが必要な場合は、次のパッケージでそれをキャッチする必要があります)。 time.sleepでは、リモートサーバーからすべてのデータパッケージを取得し、ブラウザにデータを送信できます。私は何か間違っているのですか?それとも私は十分知らないのですか?助けてもらえますか?ソケットPythonからのデータ受信時にスリープ状態にする必要がありますか?

コード:

# coding: utf-8 
import socket 
import sys 
import time 
from thread import * 

max_conn = 5 
buffer_size = 4096 


def proxy_server(webserver, port, conn, addr, data): 
    try: 
     remote_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
     remote_sock.connect((webserver, port)) 
     remote_sock.send(data) 
     response_text = '' 
     while True: 
      time.sleep(0.5) 
      response = remote_sock.recv(buffer_size) 
      response_text += response 
      if len(response) < buffer_size: 
       remote_sock.close() 
       break 
     conn.sendall(response_text) 
     conn.close() 
    except socket.error, msg: 
     print 'Proccessing error. Error Code: ' + str(msg[0]) + ', Wiadomość: ' + msg[1] 
     remote_sock.close() 
     conn.close() 
     sys.exit() 


def conn_string(conn, data, address): 
    header = data.split('\r\n') 
    method, address, protocol = header[0].split(' ') 
    host_key, host_value = header[1].split(': ') 
    proxy_server(host_value, 80, conn, address, data) 


def start(): 
    try: 
     sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
     sock.bind(('', 8001)) 
     sock.listen(max_conn) 
     print 'Proxy: on' 
    except socket.error, msg: 
     print 'Failed creating a socket. Error Code: ' + str(msg[0]) + ', Wiadomość: ' + msg[1] 
     sys.exit() 

    while True: 
     try: 
      connection, address = sock.accept() 
      data = connection.recv(buffer_size) 
      # start_new_thread(conn_string, (connection, data, address)) 
      conn_string(connection, data, address) 
     except KeyboardInterrupt: 
      sock.close() 
      print "Socket closed" 
      sys.exit() 

if __name__ == "__main__": 
    start() 
+0

コンテンツ長のヘッダーがある場合は、正確なバイト数がrecvされるまで、属性の値を使用してsocket recvをループオーバーします。 –

答えて

1

time.sleep()を使用しないでください、それはあなたのプロキシが非常に遅い、およびその効率的ではないことができます。
ソケットを非ブロックモードでタイムアウトを設定して設定する必要があります。
socket.settimeout()
proxy_serverにいくつか修正を加えましたが、現在ははるかに速くする必要があります。

def proxy_server(webserver, port, conn, addr, data): 
    try: 
     remote_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
     remote_sock.connect((webserver, port)) 
     remote_sock.send(data) 
     remote_sock.settimeout(0.5) 
     response_text = '' 
     while True: 
      try : 
       response = remote_sock.recv(buffer_size) 
       if len(response) == 0: 
        break 
      except : 
       break 
      response_text += response 
     conn.sendall(response_text) 
    except socket.error, msg: 
     if str(msg) != 'timed out' : 
      print 'Proccessing error. Error Code: ' + str(msg[0]) + ', Wiadomość: ' + msg[1] 
    remote_sock.close() 
    conn.close() 

あなたのコードの残りの部分はかなりOKですが、あなたは、同時に複数のクライアントを処理する場合
をマルチスレッド使用することをお勧めします。

+0

ノンブロッキングソケットの場合、マルチスレッドを使用する必要はありません。select()またはpoll()を使用して、読み書きが必要なソケットを見つけて、それらをすべて単一のスレッドで処理することができます。これは、標準的なマルチスレッドの問題(競合状態、デッドロック、ミューテックスなど)をすべて避けるという利点があります。 –

+0

はい、あなたはそれについて正しいです。サーバのタイムアウトが非常に低いか、クライアントがほんのわずかであると仮定します。 –

+0

経験豊富なタイムアウトは、TCPベースのサーバーでは決して必要ありません(サーバーが明示的に時間関連の何かを実際に行っている場合を除きます)。むしろ、すべてが(そして最高のパフォーマンスを得るためには)純粋にイベント駆動型でなければなりません。 –

関連する問題