如何使用Python流式套接字作为代理?

2024-10-01 07:48:36 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图编写一个python进程,它监听端口,当客户机连接到它时,它启动一个执行以下操作的线程:

  1. 连接到远程服务(http://193.108.24.18:8000/magicFM)

  2. 将接收到的任何数据传递到连接的客户端(恰好是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()

但它失败了。。。有:

^{pr2}$

Tags: iphttp代理size进程portbuffersocket
3条回答

扩展glglglglgl的答案:你的问题在于破坏协议。在

HTTP协议指定:

  • 用户请求GET /magicFM ...
  • 使用元数据200 OK ...的服务器响应
  • 服务器持续响应实际数据

查看更多详细信息:http://en.wikipedia.org/wiki/HTTP

urllib2.urlopen隐藏了所有这些复杂性,使其看起来像读取文件一样简单,尽管您的客户机希望代理的行为与普通的http服务器一样。这里{}对你来说是一个错误的抽象。最好的策略是打开服务器的套接字并启动两个并行循环:

  • 从客户端读取,写入服务器
  • 从服务器读取,写入客户端

(或者在一个循环中执行非阻塞读取;或者执行asyncio)

可能会有一个复杂的问题:http协议指定“Host”头,您的客户端将在请求中将代理地址作为值发送给代理,这取决于您的无线服务器的行为,您可能需要将客户端请求中的“Host:…”重写为正确的地址(尽管在现代Internet中,这通常并不重要)。在

您将注意到的另一个有趣的副作用是:代理将不包含任何有关要打开的特定URL的信息,因为您的媒体客户端将为您提供这些信息。在

我只能猜测,但也许你的问题出在客户端。在

我不知道您的客户试图建立哪些连接,但可能在期望的内容和实际传输的内容之间存在冲突:

  • 从客户机获得连接,它可能会发送一些请求数据。在
  • 如果这些数据与使用urllib2.urlopen()发送到流的数据不匹配,或者来自那里的答案不匹配,客户端将取消连接,让您有一个断开的套接字。在

我看到两种解决方案:

或者

  • 尝试将应答行(HTTP/x.x 200 OK或类似的)和标题发送回您的客户机-它应该在req.headers左右的某个地方。在

或者

  • 根本不要做urllib2.urlopen(),只需打开一个到那里的常规套接字连接。但是,您可能不得不篡改请求的头,Host:头可能必须被替换。在

首先,要使用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复用数据流。在

我现在没有时间,这段代码更像是一个草图。你需要正确的错误处理,也许在这个函数中有很好的错误消息,但是如果没有人提出一个完整的解决方案,我可能会努力完成这段代码。在

相关问题 更多 >