【问题标题】:Terminal Services dropping messages终端服务丢弃消息
【发布时间】:2013-05-23 01:23:25
【问题描述】:

拥有一个通过终端服务/远程桌面服务虚拟通道 API 进行通信的应用程序。随机且周期性地(大约每 20,000 条消息),客户端将发送一条消息(VirtualChannelWrite 返回 0,并使用 CHANNEL_EVENT_WRITE_COMPLETE 调用 VirtualChannelOpenEvent),但服务器调用 WTSVirtualChannelRead 永远不会读取该消息。服务器上没有错误消息。客户端写入没有时间差异的迹象。

在服务器端,虚拟通道只能从一个线程访问读写,所以不是线程问题(WTSVirtualChannelRead 和 WTSVirtualChannelWrite 不是线程安全的)。

任何人都了解导致丢失消息的原因吗?

我想知道这个 API 是否根本无法针对高密度的客户端到服务器流量进行扩展(从未见过从服务器到客户端的丢弃消息)。我想知道服务器上的重叠 I/O 解决方案是否会表现得更好,每 MSDN:“WTSVirtualChannelQuery 返回一个文件句柄,您可以使用它来执行异步(重叠)读写操作”。

【问题讨论】:

    标签: remote-desktop terminal-services


    【解决方案1】:

    WTSVirtualChannelRead 和 WTSVirtualChannelWrite API 是 Microsoft 设计不佳的 API 之一。

    首先,由于异步 I/O,您不能从任何线程使用 WTSVirtualChannelRead() 和 WTSVirtualChannelWrite()。您必须使用 WTSVirtualChannelQuery() 来获取文件句柄,然后通过 ReadFile() 和 WriteFile() 对虚拟通道进行读取和写入。

    此外,在读取虚拟通道时,您必须处理您必须处理 ReadFile() 立即返回的情况,因为有可用数据和 ReadFile() 被阻塞,您等待 I/O 完成然后调用 GetOverLappedResult ()。

    更多详情请关注http://blogs.msdn.com/b/rds/archive/2007/09/20/dynamic-virtual-channels.aspx

    【讨论】:

    • 同意重叠 I/O 是关键。我的解决方案有点不同;评论太长了,所以发布为另一个答案。
    【解决方案2】:

    Angry Coder 的answer 是正确的,您必须使用重叠 I/O。我找到了一个在细节上略有不同的解决方案:

    首先,正如我在问题中提到的那样,只要在同一个线程中调用 WTSVirtualChannelRead() 和 WTSVirtualChannelWrite(),它们通常就可以工作。但是 WTSVirtualChannelRead() 仍然偶尔会丢失消息。显然解决方法是block for 1 sec。需要写的时候不行,读阻塞的时候不行。

    其次,我根据this article在.NET中实现了Overlapped I/O。使用I/O完成端口,读和写总是在回调方法中完成,无需区分有无数据。

    第三,不需要实现动态虚拟通道;根据Virtual Channel Client API,这一切都适用于静态频道。

    【讨论】:

    • 你能分享你的代码吗?我正在努力解决同样的问题,我尝试使用 WTSVirtualChannelQuery 但没有运气。
    • 对不起,我不能,但是您为什么不发布一个新问题并在评论中添加一个链接?我会尽力回答的。
    猜你喜欢
    • 1970-01-01
    • 2021-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多