将TCP用于实时命令:Nagle算法会导致巨大的延迟,我该怎么办?

将TCP用于实时命令:Nagle算法会导致巨大的延迟,我该怎么办?,tcp,network-programming,client-server,network-protocols,real-time,Tcp,Network Programming,Client Server,Network Protocols,Real Time,我正在编写一个套接字服务器和flash游戏客户端。游戏需要实时命令,如移动和转弯。服务器尽快将这些命令发送到客户机是很重要的,因为其他客户机将与移动/转向客户机大量失同步 这是Nagle算法引起的问题的一个示例: 注意:如果您想了解这些命令的含义,请参阅下面的命令表 第一个是我移动的船(向前移动+向右移动,向前移动已收到,但没有向右移动) 客户端发送命令: 84796: Sending data: 2#4 84796: Sending data: 2#2 84904: Sending data:

我正在编写一个套接字服务器和flash游戏客户端。游戏需要实时命令,如移动和转弯。服务器尽快将这些命令发送到客户机是很重要的,因为其他客户机将与移动/转向客户机大量失同步

这是Nagle算法引起的问题的一个示例:

注意:如果您想了解这些命令的含义,请参阅下面的命令表

第一个是我移动的船(向前移动+向右移动,向前移动已收到,但没有向右移动)

客户端发送命令:

84796: Sending data: 2#4
84796: Sending data: 2#2
84904: Sending data: 2#3
84904: Sending data: 2#0
86187: Sending data: 2#4
86188: Sending data: 2#2
86374: Sending data: 2#3
86404: Sending data: 2#0
79244: Raw receive: 3#3#4$
79244: New command: 3#3#4
79398: Raw receive: 3#3#2$3#3#3$3#3#0$
79399: New command: 3#3#2
79399: New command: 3#3#3
79399: New command: 3#3#0
80635: Raw receive: 3#3#4$
80635: New command: 3#3#4
80908: Raw receive: 3#3#2$3#3#3$3#3#0$
80908: New command: 3#3#2
80908: New command: 3#3#3
80908: New command: 3#3#0
接收命令的客户端:

84796: Sending data: 2#4
84796: Sending data: 2#2
84904: Sending data: 2#3
84904: Sending data: 2#0
86187: Sending data: 2#4
86188: Sending data: 2#2
86374: Sending data: 2#3
86404: Sending data: 2#0
79244: Raw receive: 3#3#4$
79244: New command: 3#3#4
79398: Raw receive: 3#3#2$3#3#3$3#3#0$
79399: New command: 3#3#2
79399: New command: 3#3#3
79399: New command: 3#3#0
80635: Raw receive: 3#3#4$
80635: New command: 3#3#4
80908: Raw receive: 3#3#2$3#3#3$3#3#0$
80908: New command: 3#3#2
80908: New command: 3#3#3
80908: New command: 3#3#0
“瞬间”是一个奇怪的术语,它并不是我想说的意思, 但在这里,似乎是上一个命令之后的时间量(以毫秒为单位)

  • 前进 客户端A发送(时刻:0),客户端B接收(时刻:0)

  • 右转 客户端A发送(时刻:0),客户端B接收(时刻:155)

  • 别动 客户端A发送(时刻:108),客户端B接收(时刻:0)

  • 停止转动 客户端A发送(时刻:0),客户端B接收(时刻:0)

  • 前进 客户A发送(时刻:1283),客户B接收(时刻:1236)

  • 右转 客户A发送(时刻:1),客户B接收(时刻:273)

  • 停止运动 客户A发送(时间:186),客户B接收(时间:0)

  • 停止转动 客户端A发送(时刻:30),客户端B接收(时刻:0)

  • 这是与命令对应的命令表:

    84796: Sending data: 2#4
    84796: Sending data: 2#2
    84904: Sending data: 2#3
    84904: Sending data: 2#0
    86187: Sending data: 2#4
    86188: Sending data: 2#2
    86374: Sending data: 2#3
    86404: Sending data: 2#0
    
    79244: Raw receive: 3#3#4$
    79244: New command: 3#3#4
    79398: Raw receive: 3#3#2$3#3#3$3#3#0$
    79399: New command: 3#3#2
    79399: New command: 3#3#3
    79399: New command: 3#3#0
    80635: Raw receive: 3#3#4$
    80635: New command: 3#3#4
    80908: Raw receive: 3#3#2$3#3#3$3#3#0$
    80908: New command: 3#3#2
    80908: New command: 3#3#3
    80908: New command: 3#3#0
    
    客户端->服务器

    服务器->客户端

    因此,您可以看到,由于“Nagle”,这些命令完全不同步。这会导致其他客户端在接收开始移动命令的同时接收停止移动命令,从而导致该播放器根本不移动

    这就是为什么我需要TCP服务器以尽可能快的速度实时发送这些命令。一个简单的解决方法是简单地禁用Nagle。然而,我有一点(注意,他关于tcp消息部分的建议是在我的系统中实现的,但与时间无关),并注意到人们绝对不建议禁用Nagle

    我真的不应该因为这个原因禁用Nagle算法,而是应该寻找其他解决方案吗?为什么

    提前谢谢。
    -Tom

    您想使用TCP\u节点延迟来关闭该套接字的nagle算法。现代操作系统中有一些设置可以在系统范围内禁用它,这是不受欢迎的,但没有理由不使用一个需要低延迟的套接字


    请注意,您的交换机、路由器、ISP的交换机。。。。等也可能唠叨他们的黑色小内脏。这些肮脏的小动物会读数据包,所以他们有时会随意重写


    查看RTP(通过UDP运行)以获得更具网络生存能力的方法。

    如果需要尽可能快的速度,您应该使用UDP

    但是,请注意,TCP提供交货和订单保证,而UDP不提供任何保证

    这一点在这个应用程序中似乎非常重要,因此您必须在上面分层您自己的确认/重试命令排序机制

    如果你想坚持使用TCP,TCP__;u NODELAY会有所帮助。随着游戏的发展,您可能最终需要TCP非常适合的数据流,而无需TCP_NODELAY


    RFC1006规范化了通过TCP流发送数据包的机制。

    如果您的目标是让船只在每个人的屏幕上都做同样的事情,那么您必须发送位置更新。您不能仅仅因为客户A做了以下事情就认为:

    • 左转
    • 等待100毫秒
    • 停止转动
    客户端B将看到完全相同的100毫秒延迟。Nagle缓冲只会让这变得更极端——但总会有抖动和不同的延迟

    您确实需要发送以下内容:

    • (我在位置X1,Y1,航向Z1)左转
    • (我在位置X2,Y2,航向Z2)停止转向

    这样客户端就会不断地重新同步。

    请注意,Windows不仅实现了Nagle,而且还实现了Nagle。这会给您在单个TCP消息上额外的200毫秒延迟。据我所知,除非通过注册表项(以及在某些情况下启用注册表项的热补丁),否则无法在Windows上更改此设置。

    我应该提供更多背景信息。我正在这么做,所以别担心。我在这篇文章中提出的主要问题已经解决了。谢谢。OP没有说他需要尽快完成。他只是说他希望立即发送数据,这是明显不同的。在所有其他条件相同的情况下,转向唠叨比直接跳到UDP要好得多。这让人困惑,两个人在一个线程中有相同的名字。唠叨算法,而不是“算术”。