简单的Python本地代理-几乎可以运行

4
我正在开发一个稍大的项目,需要在Python中制作一个本地主机代理。我所写的方式是在本地主机上以8080端口创建了一个基于socket和SOCK_STREAM的TCP服务器。它接受来自本地主机的请求,在通过切片、string.find()和gethostbyname()查找到目标IP地址后,打开另一个TCP套接字,发送请求并收到回复。然后,它将回复传递回本地主机代理,再由代理将其传递回浏览器。这是带有充足调试消息和调试文件的代码,可以收集浏览器请求和收到的回复(请注意,这只是一个原型,因此使用限定循环而不是while 1循环)。
import socket

local = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

f = open('test.txt', 'a')
local.bind(('localhost', 8080))
local.listen(5)
for i in xrange(20):
    print '=====%d=====\n' % i
    out = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    data, addr = local.accept()
    print 'Connection accepted'
    buffer = data.recv(4096)
    print 'data recieved'
    f.write('=============================================================\n')
    f.write(buffer)
    end = buffer.find('\n')

    print buffer
    #print buffer[:end]
    host = buffer[:end].split()[1]
    end = host[7:].find('/')

    print host[7:(end+7)]
    host_ip = socket.gethostbyname(host[7:(end+7)])
    #print 'remote host: ' + host + ' IP: ' + host_ip
    print 'sending buffer to remote host'
    out.connect((host_ip, 80))
    out.sendall(buffer)
    print 'recieving data from remote host'
    reply = out.recv(4096)
    out.close()
    print 'data recieved from remote host'
    f.write('+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n')
    f.write(reply)
    f.write('\n\n\n')
    print 'sending data back to local host'
    data.sendall(reply)
    print 'data sent'
local.close()
out.close()    
f.close()

现在我的问题是,似乎前几个请求都没问题,它会获取HTML和一些图像,但在某一点上它总是停在“数据接收”这一点上并退出,因为它没有收到数据,即缓冲区为空。浏览器仍然显示页面元素正在加载,但当它停止并查看文本日志文件时,我发现缓冲区为空,这意味着浏览器没有向代理提交任何内容? 我猜测问题可能出在浏览器提交请求的方式以及我的脚本对此行为反应不当上。
我知道我可以使用Twist框架,但我想学习自己编写这种东西。我一直在阅读有关SocketServer的资料,我可能会使用它,但是我不知道它是否能解决问题,因为实际上我真的不明白问题的原因。我的脚本对浏览器来说太慢了吗?服务器会发送多个答案而我的接收套接字应该监听更多的数据包吗?我的缓冲区大小(4096)太小了吗?
我真的很感谢您能指点一下方向。
谢谢!

好的,我刚刚进行了几项测试。我将输出套接字的缓冲区增加到65536,以便获取所有更大的图像,并且似乎已经将一些回复传递回浏览器。然而,现在我在第23行遇到了索引错误,进一步表明从本地浏览器接收GET的变量缓冲区...是空的。 - Protagonist
我刚刚重写了脚本,使用了线程和队列。我使用了queue.get(True, 10)函数,如果一个线程在10秒内无法从队列中获取任何内容,则会引发异常。_猜猜看?_它会引发异常。似乎由于某种原因,绑定到本地主机的本地套接字不会从本地主机接受任何连接,因此它无法获取本地主机的出站请求,这导致了所有问题。由于学校的原因,今天我必须离开它。 - Protagonist
你似乎走在正确的道路上 - 如果你使用的是Win操作系统,尝试使用“127.0.0.1”而不是“localhost”。 - Iliyan Bobev
1个回答

2

好的,我设法回答了我的问题。我之前怀疑的部分是对的——浏览器正在等待某些东西,那个东西就是回复。

我启动了 Wire Shark,做了一些实验,发现我的代理在 Wireshark 中产生了很多丑陋的 TCP RST。我还注意到,在正常连接中,许多服务器回复被分成几个不同的数据包。

基本上,我的程序没有从服务器获取所有的答案,因为 out.recv 只得到了回复的一部分。显然的答案是制作一个循环并监听所有回复。我在 http://www.binarytides.com/receive-full-data-with-the-recv-socket-function-in-python/ 找到了完美的解决方案。

我很快重新编写了我的程序,现在它像魅力一样工作。现在我可以继续进行整个项目。

我希望这可以帮助未来遇到类似问题的其他人。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接