奇怪的Flash AS3 xml Socket行为

7

我遇到了一个无法理解的问题。

为了理解它,我编写了一个AS3套接字客户端和一个Python/Twisted服务器。您可以在下面查看两个应用程序的代码。

让我们同时启动两个客户端,将它们排列好以便您可以看到两个窗口,并在两个窗口中按连接按钮。然后按住任何一个按钮。

我期望的是:

按下按钮的客户端向服务器发送一个消息“一些数据”,然后服务器将此消息发送给所有客户端(包括原始发送方)。

然后每个客户端将“connectButton”按钮向右移动,并以以下格式在日志中打印时间的消息:“分:秒:毫秒”。

出现了什么问题:

在发送消息的客户端中,运动是平滑的,但在其他所有客户端中,运动都是不连续的。

这是因为对于那些客户端,消息到达的时间比原始发送方晚。如果我们有三个客户端(让我们称它们为A、B、C),并从A发送一条消息,则B和C的发送时间日志将相同。

为什么其他客户端接收这些消息比原始发送方晚?

顺便说一下,在ubuntu 10.04/chrome上,所有运动都是平滑的。在两个独立的Chrome浏览器中启动了两个客户端。

Windows截图

Linux截图

日志清单,四个客户端同时:

[16:29:33.280858] 62.140.224.1 >> some data
[16:29:33.280912] 87.249.9.98 << some data
[16:29:33.280970] 87.249.9.98 << some data
[16:29:33.281025] 87.249.9.98 << some data
[16:29:33.281079] 62.140.224.1 << some data
[16:29:33.323267] 62.140.224.1 >> some data
[16:29:33.323326] 87.249.9.98 << some data
[16:29:33.323386] 87.249.9.98 << some data
[16:29:33.323440] 87.249.9.98 << some data
[16:29:33.323493] 62.140.224.1 << some data
[16:29:34.123435] 62.140.224.1 >> some data
[16:29:34.123525] 87.249.9.98 << some data
[16:29:34.123593] 87.249.9.98 << some data
[16:29:34.123648] 87.249.9.98 << some data
[16:29:34.123702] 62.140.224.1 << some data

AS3客户端代码,我只保留了相关部分,完整代码在此处

        private var socket           :XMLSocket;

        socket = new XMLSocket();
        socket.addEventListener(DataEvent.DATA, dataHandler);

        private function dataHandler(event:DataEvent):void
        {
            var now:Date = new Date();
            textField.appendText(event.data + "          time = " + now.getMinutes() + ":" + now.getSeconds() + ":" + now.getMilliseconds() + "\n");
            connectButton.x += 2;
        }

        private function keyDownHandler(event:KeyboardEvent):void
        {
            socket.send("some data");
        }

        private function connectMouseDownHandler(event:MouseEvent):void
        {
            var connectAddress:String = "ep1c.org";
            var connectPort:Number = 13250;

            Security.loadPolicyFile("xmlsocket://" + connectAddress + ":" + String(connectPort));
            socket.connect(connectAddress, connectPort);
        }
Python服务器代码

1
这只是一个想法,但我认为如果HTML中的SWF对象没有焦点,它将以较低的帧速率运行。这可以解释“卡顿”的原因,但在ubuntu/chrome上运行良好,这可能是该设置中的Flash播放器处理方式不同。您是否尝试在不同的机器上测试,而不仅仅是在同一台机器上?我模糊地记得阅读过,速率可能会急剧下降到约2 FPS。 - The_asMan
谢谢,我尝试了两台不同的Ubuntu机器和四台Windows机器,但结果都一样。当我在两台不同的机器上运行两个客户端(所有客户端都有焦点)时,等待数据的客户端会出现卡顿和时间日志不准确的问题(就像我在下面的问题中发布的那样)。 - Rnd_d
2个回答

4
你可能正在经历确认延迟和/或Nagle算法的某种组合。这两个因素都可以有选择地延迟TCP会话中数据的移动,它们的实现因平台而异。
尝试使用setsockopt()TCP_NODELAY在套接字上禁用Nagle。
据我所知,Windows不允许您按套接字基础禁用ACK延迟:您必须编辑注册表并将其禁用所有TCP。因此,首先尝试TCP_NODELAY。如果这样做不起作用,则尝试禁用ACK延迟。即使对于您的应用程序来说,编辑注册表并不切实际,只要知道ACK延迟是否是问题,就可以为其他解决方法指明正确方向。

哇,看起来它可以工作了!我在Twisted服务器的connectionMade方法中设置了self.transport.setTcpNoDelay(True) - Rnd_d

1

我知道我回复有点晚了,但很可能这是由于服务器和非发起客户端之间建立TCP连接所需的时间。

这个想法是,已经在发起的客户端和服务器之间建立了TCP连接(在第一个客户端的消息之前设置),因此在这种情况下消除了进行三次握手所需的时间。

您可以通过几种方式进行测试,最简单的方法是在实际消息处理之前建立连接(例如通过向每个人发送虚拟消息)。

如果您不想与每个客户端建立连接,也可以切换到UDP,但这样会失去TCP的可靠性。

我不确定我是否理解了您关于Linux的说明。您是说它在Linux上按预期工作,但在Windows上没有?如果是这样,我们需要了解更多有关您的设置的信息,例如所有客户端是否在同一主机上运行?在同一个浏览器实例中吗?


不晚,谢谢。在数据发送之前已经建立了连接。我可以通过打开两个客户端(问题开头的链接)并与它们互动来检查它。是的,在Linux上它按照我的意图工作。同一主机,相同的Flash播放器作为客户端,在两者上都使用Chrome。 - Rnd_d

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