4

我正在做自己的一个稍微大一点的项目,我需要在 python 中创建一个 localhost 代理。

我写我的方式是在 localhost 的 8080 端口上有一个 TCP 服务器(使用套接字和 SOCK_STREAM)。它接受来自本地主机的请求,使用切片、string.find() 和 gethostbyname() 找到目标 IP,因此它打开另一个 TCP 套接字,发送请求并 recv 回复。之后,它将回复转发回 localhost 代理,该代理又将其返回给浏览器。

这是带有大量调试消息和调试文件的代码,用于收集浏览器的请求和收到的回复(另请注意,这只是一个原型,因此有限的 for 循环而不是 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) 是否太小?

我真的很感激朝着正确的方向轻推。

谢谢!

4

1 回答 1

2

好吧,我设法回答了我的问题。我之前怀疑的部分是正确的——浏览器正在等待某事,而某事正在回复。

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

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

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

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

于 2012-10-13T15:54:49.950 回答