【发布时间】:2012-10-10 14:00:18
【问题描述】:
我正在做我自己的一个稍微大一点的项目,我需要在 python 中创建一个本地主机代理。
我写我的方式是在 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) 是否太小?
我真的很感激朝着正确的方向轻推。
谢谢!
【问题讨论】:
-
好的,我刚刚做了一些测试。我将输出套接字的缓冲区增加到 65536,这样我就可以获得所有更大的图像,并且它似乎已经将更多的回复转发回浏览器。但是,现在我在第 23 行遇到了一个索引错误,进一步表明从本地浏览器接收 GET 的变量缓冲区只是......为空。
-
我还重写了刚才的脚本,使用线程和队列。如果线程在 10 秒内无法从队列中获取任何内容,我使用 queue.get(True, 10) 函数引发异常。 你猜怎么着? 它引发了异常。似乎由于某种原因,绑定到 localhost 的本地套接字不是 .accept()'ing 来自 localhost 的任何连接,因此它无法获取 localhost 的出站请求,这会导致所有问题。由于学校的关系,这是我今天不得不离开的地方。
-
你似乎在正确的道路上 - 如果你在 Win OS 上尝试使用“127.0.0.1”而不是“localhost”