我遇到了一个我无法理解的问题。
为了理解它,我在AS3上编写了一个套接字客户端,在python / twisted上编写了一个服务器,你可以在下面看到这两个应用程序的代码。
让我们同时启动两个clients,排列它们,以便您可以在两个窗口中看到两个窗口并按下连接按钮。然后按住任何按钮。
我期待的是什么:
使用按下按钮的客户端向服务器发送消息“某些数据”,然后服务器将此消息发送给所有客户端(包括原始发件人)。
然后每个客户端向右移动按钮'connectButton'并按照以下格式随时间向日志打印消息:“min:secs:milliseconds”。
出了什么问题:
在发送消息的客户端中,动作是平滑的,但在所有其他客户端中,动作都是生涩的。
这是因为发送给这些客户端的邮件的时间晚于到原始发送客户端的邮件。如果我们有三个客户端(让我们将它们命名为A,B,C)并且我们从A发送消息,则B和C的发送时间日志将是相同的。
为什么其他客户端会比原始发件人晚收到此邮件?
顺便说一句,在ubuntu 10.04 / chrome上,所有的动作都很流畅。两个客户在分开的chromes中推出。
同时列出日志,四个客户端:
[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客户端代码,我只留下相关部分full code here。
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);
}
答案 0 :(得分:4)
您可能会遇到ACK delay和/或Nagle's algorithm的某种组合。这两者都可以选择性地延迟TCP会话上的数据移动,并且它们的实现因平台而异。
尝试在套接字上使用setsockopt()
和TCP_NODELAY
来禁用Nagle。
AFIK,Windows不允许您在每个插槽的基础上禁用ACK延迟:您必须edit the registry并为所有TCP禁用它。所以先试试TCP_NODELAY
。如果这不起作用,那么试验禁用ACK延迟。即使注册表编辑对您的应用程序不实用,只要知道ACK延迟是否是问题,就可以指出您正确的方向进行其他解决方案。
答案 1 :(得分:1)
我知道这有点晚了,但很可能这是因为在服务器和非启动客户端之间建立TCP连接所需的时间。
这个想法是在发起客户端和服务器之间已经建立了TCP连接(它在第一个客户端消息之前设置),因此在这种情况下消除了进行3次握手所需的时间。
您可以通过几种方式对此进行测试,最简单的方法是在真正的消息处理之前建立连接(例如,通过向每个消息处理发送虚拟消息)。
如果您不想与每个客户端建立连接,也可以切换到UDP,但是会失去TCP的可靠性。
我不确定我理解你关于Linux的说明。你是说它在Linux上有效但不是Windows吗?如果是这样,我们需要了解有关您的设置的更多信息,例如,所有客户端是否在同一主机上运行?在同一个浏览器实例中?