我正在尝试编写一个侦听端口的python进程,当客户端连接到它时,它会启动一个执行以下操作的线程:
连接远程服务(http://193.108.24.18:8000/magicFM)
将收到的所有数据传递给连接的客户端(恰好是Windows Media Player)
故事是我想在工作中收听我的收音机,但我不能,因为我在另一个国家(仅在全国范围内可用),我无法更改计算机上的代理设置.... 但我有这个服务器,我想用作代理。
提前致谢。
以下是我到目前为止所做的事情:
#!/usr/bin/env python
import socket, urllib2
TCP_IP = '0.0.0.0'
TCP_PORT = 5566
BUFFER_SIZE = 16 * 1024 #16 kb/s
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)
conn, addr = s.accept()
print 'Connection address:', addr
req = urllib2.urlopen('http://193.108.24.18:8000/magicFM')
while 1:
chunk = req.read(BUFFER_SIZE)
if not chunk: break
conn.send(chunk)
conn.close()
但它失败了...:
Traceback (most recent call last):
File "./magicfmproxy.py", line 17, in ?
conn.send(chunk)
socket.error: (32, 'Broken pipe')
答案 0 :(得分:2)
首先,要使用TCP连接到远程站点,请使用此代码
import socket, struct
def connectToHost(host, port=80, timeout=0):
try:
sock=socket.socket()
timeval=struct.pack("2I", timeout, 0)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, timeval)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDTIMEO, timeval)
sock.connect((host, port))
return sock
except:
return None
您现在有一个连接到远程服务器的开放式套接字。您必须创建一个侦听套接字并等待此套接字进行连接。只要连接存在,就使用select
多路复用数据流。
我现在没有时间,这段代码更像是草图的样子。您需要在此函数中进行正确的错误处理和错误消息,但如果没有人提供完整的解决方案,我可能会努力完成此代码。
答案 1 :(得分:1)
我只能猜测,但也许你的问题存在于客户端。
我不知道您的客户尝试建立哪些连接,但可能在预期内容和实际传输内容之间存在冲突:
urllib2.urlopen()
发送到流的数据不匹配,或者那里的答案不匹配,则客户端取消连接,让您的套接字断开。我看到两个解决方案:
无论
HTTP/x.x 200 OK
或类似内容)和标题发送回客户端 - 它应该位于req.headers
左右。或
urllib2.urlopen()
,只是打开常规的套接字连接。但是,您可能不得不篡改请求的标头 - Host:
标头可能必须被替换。答案 2 :(得分:0)
扩展glglgl回答:你的问题在于破解协议。
HTTP协议指定:
GET /magicFM ...
200 OK ...
详情请见http://en.wikipedia.org/wiki/HTTP
urllib2.urlopen
隐藏了所有这些复杂功能,使其看起来像读取文件一样简单,尽管您的客户端希望代理能够像普通的http服务器一样运行。这里urlopen
对你来说是错误的抽象。最好的策略是打开socket到服务器并启动两个并行循环:
(或使用非阻塞读取在一个循环中执行;或执行asyncio)
可能存在复杂问题:http-protocol指定客户端将请求代理地址作为值发送给客户端的“主机”标头,具体取决于您可能需要重写“无线电服务器”的行为。 ..“在客户要求纠正地址(虽然在现代互联网上通常无关紧要)。
您会注意到的另一个有趣的副作用是:代理不会包含有关要打开的特定URL的任何信息,因为您的媒体客户端会为您提供这些信息。