通过代理使用HTTP传输的RTSP

6
我正在尝试使用代理通过HTTP获取RTSP流。Real客户端的行为似乎有点混乱:它同时尝试所有可能的端口、方法和协议。唯一有效的方法是通过80端口进行HTTP GET请求。确实发出了这样的请求,并在服务器上接收到。以下是代理向服务器发送请求时的样子:
GET /SmpDsBhgRl83c52ef2-d0f4-41ac-bada-93e5350f67d1?1="1" HTTP/1.0\r\n
Connection: Keep-Alive\r\n
Host: 10.194.5.162:80\r\n
Pragma: no-cache\r\n
User-Agent: RealPlayer G2\r\n
Expires: Mon, 18 May 1974 00:00:00 GMT\r\n
Accept: application/x-rtsp-tunnelled, */*\r\n
ClientID: WinNT_5.1_6.0.14.806_RealPlayer_R41UKD_en-GB_686\r\n
X-Actual-URL: rtsp://10.194.5.162:554/01.mp3\r\n
\r\n

这是服务器的响应:

HTTP/1.0 200 OK\r\n
Server: RMServer 1.0\r\n
Expires: Mon, 18 May 1974 00:00:00 GMT\r\n
Pragma: no-cache\r\n
x-server-ipaddress: 10.194.5.162\r\n
Content-type: audio/x-pn-realaudio\r\n
\r\n

在这一点上,服务器传来了另外4个字节(它们的值为48 02 02 00)- 就是这样,没有更多的内容。此时,服务器是否期望客户端做出任何回应?如果是,该做什么?这种操作模式是否有效?
关于这个问题的一些更多信息:显然,RealPlayer内置的通过HTTP使用RTSP的机制的预期工作方式如下:
  1. 尝试连接以下端口:80、8080、554、7070。(也可以直接尝试通过在端口80上发出GET请求http://hostname:port/mediafilename以直接下载文件)
  2. 对于以上每个端口,创建2个连接。
  3. 向其中一个连接发送GET请求到url http://hostname:port/SmpDsBhgRl<guid>?1="1",其中<guid>是新创建的GUID。添加一个名为X-Actual-URL的头部到此请求中,其中包含原始的RTSP URL。
  4. 在另一个连接上向URL http://hostname:port/SmpDsBhgRl 发送POST请求,并将上述GUID作为请求体的一部分发送。发送32767字节的Content-Length头部,以防止代理过早地关闭连接。
  5. 开始通过POST请求向服务器发出命令,并在GET响应中获取相应的RTSP流。
奇怪的事情(如果上面不够奇怪)是,例如,它与Squid一起使用,但如果您使用3128或8080端口,则无法使用!不知何故,客户端使用它连接到的端口来决定请求的顺序或何时取消请求,但无论如何,难以置信的是,它可以使用代理端口9090、3129、8081,但不能使用3128或8080。

更新#2:这里是RealPlayer的源代码,解释了上述行为。尽管如此,仍然没有解决方案。

更新#3:好吧,在上面的情况下,48 02 02 00的魔术值是清晰的:48 == 'h'代表HTTP_RESPONSE,下一个02是以下数据的长度,下一个02被称为POST_NOT_RECEIVED(意思是POST请求在相应的GET请求后一秒钟内未到达服务器)。

更新 #4:这种行为(即使用巨大Content-Length的POST请求)也是WebEx使用的ActiveX的特征(以及可能许多其他需要与服务器建立打开通道的网络应用程序的特征)。


服务器的HTTP 200 OK响应是否有效?!我的服务器以前也像你的一样响应,但是RealPlayer在打开GET和POST连接后停止响应。然后我在响应体中添加了48 02 00 00和Content-Length: 4属性,它就可以工作了...也许你需要修改你的HTTP OK响应,并在接收到POST连接后发送它,而不是在此之前。 - Cipi
2个回答

3
首先,您可能需要阅读这篇文章:http://developer.apple.com/quicktime/icefloe/dispatch028.html
其次,HTTP请求(GET和POST)需要格式化,以便正确代理。我见过一些代理服务器会缓存太多的POST请求,导致它无法到达服务器。这些代理服务器存在缺陷,但您无法解决这个问题,我也无法解决这个问题。主要是在反病毒软件中看到这种情况,它们试图对从浏览器发出的POST请求进行透明代理,以扫描其中包含的私人信息,例如社会安全号码。您可能遇到了同样的问题。
您是否使用McAfee杀毒软件?
此外,似乎Real发明了自己的方法来实现相同的功能,但基本设计非常相似-用于下行链路的GET,用于上行链路的POST,并带有一些魔术Cookie(在这种情况下,是GUID),以在服务器上将两者绑定在一起。无论哪种方式,POST都应该到达服务器,在您的情况下似乎没有到达。
顺便说一句,由于问题似乎出在POST请求未通过代理,那么除了GET之外,如何发布该请求?

0
  1. 尝试绕过代理服务器发出相同的请求(例如使用Netcat重放上面发布的请求),查看响应体中是否流传了超过四个字节。
  2. 查看代理服务器接收到的TCP数据包,例如通过监听运行代理服务器的机器上的TCP流量(例如使用Wireshark)。

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