代理服务器不发送所有数据python

时间:2016-12-01 00:35:25

标签: python sockets http proxy server

我正在python中创建一个HTTP代理,但我遇到麻烦,因为我的代理只会接受Web服务器响应,并且会完全忽略浏览器的下一个请求,并且数据传输就会停止。这是代码:

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

对于代码感到抱歉这只是一个试用版,我将非常感谢帮助,因为我只有14岁并且需要学习: - )

1 个答案:

答案 0 :(得分:1)

不幸的是,我并没有真正看到你的代码应该如何工作,所以我在这里想到了一个简单的HTTP代理应该是怎样的。 那么基本代理服务器应该做什么:

  1. 接受来自客户端的连接并接收HTTP请求。
  2. 解析请求并提取其目的地。
  3. 转发请求和回复。
  4. (可选)支持Connection: keep-alive
  5. 让我们一步一步地写一些非常简化的代码。

    代理如何接受客户端。应创建套接字并将其移至被动模式:

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

    建立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
    

    在TCP中,不保留消息边界,因此我们应该等到至少前两行(对于GET请求)才能知道以后要做什么:

    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 - 这就是我们知道远程对等方是否向我们发送数据的方式。我没有运行并测试过这段代码,还有一件事要做:

    1. 有可能,您将在单个client_sock.recv(1024)调用中获得多个GET请求,因为在TCP中不会保留消息边界。可能每次收到数据时都要查看其他获取请求。
    2. 请求可能因POST,HEAD,PUT,DELETE和其他类型的请求而异。相应地解析它们。
    3. 浏览器和服务器通常通过在标头中设置Connection: keep-alive选项来使用一个TCP连接,但他们也可能决定放弃它。准备好检测远程对等体关闭的断开连接和套接字(为简单起见,这在代码中称为while it_makes_sense()。)
    4. bindlistenacceptrecvsendsendallgetaddrinfoselect - 所有这些函数都可以抛出异常。抓住它们并采取相应的行动会更好。
    5. 代码目前一次为一个客户端服务。