如何加速慢速/滞后的Windows Phone 7(WP7)TCP Socket传输?

时间:2011-12-23 21:33:46

标签: sockets windows-phone-7 windows-phone-7.1 latency system.net

最近,我开始使用WP7芒果版本中引入的System.Net.Sockets类,并且一直很喜欢它,但是注意到在调试模式下传输数据的延迟与在手机上正常运行的延迟存在差异

我正在编写一个“远程控制”应用程序,当用户点击应用程序中的按钮时,该应用程序通过Wifi将单个字节传输到我的LAN上的本地服务器。因此,应用程序的感知响应性/及时性对于良好的用户体验非常重要。

通过USB电缆将手机连接到我的电脑并在调试模式下运行应用程序,TCP连接似乎可以像用户点击按钮一样快速传输数据包。

当手机与PC断开连接时,用户最多可以点击7个按钮(因此在发送所有7个字节之前,用1个字节的有效负载进行7个“发送”命令。)如果用户点击一个按钮并等待一点在点击之间,似乎有1秒的延迟。

我已经尝试将Socket.NoDelay设置为True和False,它似乎没有任何区别。

为了了解发生了什么,我使用了一个数据包嗅探器来查看流量是什么样的。

  • 当手机通过USB连接到PC(使用Wifi连接)时,每个字节都在自己的数据包中间隔约200ms。

  • 当手机在自己的Wifi连接(与USB断开连接)上运行时,字节仍然有自己的数据包,但它们都以4或5个数据包的突发组合在一起,每组相距约1000毫秒从下一个开始。

不过,从我的笔记本电脑上测量,我的Wifi网络到服务器的Ping时间是2毫秒。

我意识到缓冲“发送”可能会让手机节省能量,但是有没有办法禁用这种“延迟”?应用程序的响应能力比节省电量更重要。

6 个答案:

答案 0 :(得分:2)

确实这是一个有趣的问题!我要投入2美分,但请注意,我不是WP7上System.Net.Sockets的专家。

首先,应该忽略调试器中的性能测试。原因是无论操作系统/语言/ IDE如何,记录堆栈跟踪的额外开销总是会降低应用程序的速度。应该在发布模式下对应用程序进行性能分析,并与调试器断开连接。在你的情况下它实际上更慢的断开!好的,让我们尝试优化它。

如果您怀疑数据包正在被缓冲(这是一个合理的假设),您是否尝试过发送更大的数据包?尝试线性增加数据包大小和测量延迟。你能在设备上的代码中编写一个简单的微型分析器,即:使用DateTime.Now或Stopwatch类记录延迟与数据包大小。绘制该图可能会让您对您的理论是否正确有一个很好的了解。如果你发现10个字节(甚至100个字节)的数据包立即发送,那么我建议每次传输只需要推送更多的数据。这是一个我知道的蹩脚黑客,但如果它没有破坏......

最后你说你正在使用TCP。你可以试试UDP吗? TCP不是为实时通信而设计的,而是为准确的通信而设计的。相比之下,UDP不是错误检查,您无法保证交付,但您可以期待更快(更轻量级,更低延迟)的性能。 Skype和在线游戏等网络建立在UDP而非TCP上。如果您确实需要确认收据,您可以使用自己的Cyclic Redundancy Check进行错误检查和Request/Response (acknowledgement) protocol,通过UDP构建自己的微协议。

此类协议确实存在,请查看Reliable UDP中讨论的this previous question。有一个基于Java的RUDP实现,但我确信有些部分可以移植到C#。当然,第一步是测试UDP是否真的有帮助!


找到上一个讨论该问题的问题。也许一个Wp7问题? Poor UDP performance with Windows Phone 7.1 (Mango)

仍然有兴趣看看增加数据包大小或切换到UDP是否正常工作


好的,所以这两个建议都没有用。我找到了Nagle算法的描述,它按照你的描述对数据包进行分组。设置NoDelay应该有所帮助,但正如你所说,不是。

http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.nodelay.aspx

另外。请参阅上一个问题,其中Keepalive和NoDelay设置为开/关以手动刷新队列。他的证据很轶事,值得一试。您可以试一试并编辑您的问题以发布更多最新结果吗?

Socket "Flush" by temporarily enabling NoDelay

答案 1 :(得分:2)

安德鲁伯内特 - 汤普森在这里已经提到过,但他也写道,这对你不起作用。我不明白,我不明白为什么。那么,让我解释一下这个问题:

引入Nagle算法是为了避免必须通过TCP网络发送许多小数据包的情况。任何当前最先进的TCP堆栈都默认启用Nagle的算法!

因为:TCP本身会为通过IP连接的任何数据传输内容增加大量开销。应用程序通常不关心以优化方式通过TCP连接发送数据。所以,毕竟在操作系统的TCP堆栈内工作的Nagle算法做得非常好。

对Nagle算法及其背景的更好解释可以是found on Wikipedia

所以,你的第一次尝试:通过在套接字上设置选项TCP_NODELAY,在TCP连接上禁用Nagle的算法。这已经解决了你的问题吗?你觉得有什么不同吗?

如果不是这样,那么给我一个标志,我们将进一步深入细节。

但是,请看两次这些差异:检查细节。也许毕竟你将了解操作系统的TCP / IP-Stack中的内容是如何工作的。

答案 2 :(得分:1)

最有可能的不是软件问题。如果手机使用的是WiFi,则延迟时间可能超过70毫秒(取决于服务器的位置,有多少带宽,有多忙,对AP的干扰以及与AP的距离),但大部分延迟只是WiFi。使用GMS,CDMA,LTE或手机用于蜂窝数据的任何技术甚至更慢。我不认为除非你站在牢房塔下,否则你在蜂窝设备上的距离会低于110毫秒。

答案 3 :(得分:1)

听起来你的读/写是缓冲的。您可以尝试将Socket上的NoDelay属性设置为true,您也可以考虑修剪发送和接收缓冲区大小。响应速度降低可能是没有足够的wifi流量的副产品,我不确定是否可以调整MTU,但减少MTU可能会缩短响应时间。

所有这些只是低带宽解决方案的选项,如果您打算在任一方向上挖掘兆字节数据,您将需要更大的缓冲区而不是wifi,大到足以补偿传输延迟,通常在32K-范围内256K。

    var socket = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
    {
        NoDelay = true,
        SendBufferSize = 3,
        ReceiveBufferSize = 3,                
    };

我没有测试过,但你明白了。

答案 4 :(得分:1)

您是否尝试过设置SendBufferSize = 0?在'C'中,您可以通过将SO_SNDBUF设置为0来禁用winsock缓冲,我猜测SendBufferSize在C#中的含义相同

答案 5 :(得分:0)

您是否有机会使用Lumia 610和mikrotik接入点?

我遇到过这个问题,它让Lumia 610在最后一次连接关闭后立即关闭wifi收音机。与Lumia 800相比,这增加了可感知的延迟。所有连接都受到影响 - 只需关闭wifi即可使所有应用程序更快。我的管理员说这是mikrotiks当时没有支持WMM设置的一些功能。奇怪的是,大多数其他手机管理得很好,所以我们在开始时就把610的便宜归咎于它。

如果您仍然可以复制问题,我建议您尝试以下操作:

  • 在后台打开另一个连接并一直ping它。
  • 使用3g / gprs而不是wifi(需要将服务器暴露在互联网上)
  • 使用不同(或升级)的手机
  • 使用不同(或升级)的AP