2017-04-10 97 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的服务器来说,体验超时从来就不是必需的(当然,除非你的服务器实际上在做明确的时间相关的事情)。相反,一切都可以(并且为了获得最佳性能,应该是)完全由事件驱动。 –

相关问题