2017-04-10 96 views
0

我是新來的套接字。我已經用Python編寫了一個簡單的「代理」服務器,它將從遠程服務器捕獲數據並將其發送到我的客戶端(瀏覽器)。我想知道:有沒有辦法在沒有time.sleep的情況下發送response_text?雖然我嘗試刪除time.sleep(0.5)我只從遠程服務器獲取一個數據包,所以'Content-lenght'不等於包的長度,並且出現錯誤(我正在使用recv()獲取大小等於buffer_size的緩衝區,所以如果服務器數據需要多於一個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's,直到正確的字節數已被收回。 –

回答

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() 

你的代碼的其餘部分是相當確定的,但你可能想,如果你想在同一時間處理多個客戶端使用多線程

+0

使用非阻塞套接字,您不需要使用多線程,您可以改爲使用select()或poll()來查找哪些套接字需要從中讀取或寫入,並使用單個線程處理它們。這樣做的好處是避免了所有標準的多線程陷阱(競爭條件,死鎖,互斥鎖等) –

+0

是的,你是對的,假設服務器的超時時間很短,或者只有少數客戶端 –

+0

在我的對於基於TCP的服務器來說,體驗超時從來就不是必需的(當然,除非你的服務器實際上在做明確的時間相關的事情)。相反,一切都可以(並且爲了獲得最佳性能,應該是)完全由事件驅動。 –

相關問題