1

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

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

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

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

4

2 回答 2

1

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

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

其次,我根据这篇文章在 .NET 中实现了 Overlapped I/O 。使用I/O完成端口,读取和写入总是在回调方法中完成,因此无需区分是否有数据可用。

第三,不需要实现动态虚拟通道;这一切都适用于每个虚拟通道客户端 API的静态通道。

于 2013-05-22T17:18:07.130 回答
1

WTSVirtualChannelRead 和 WTSVirtualChannelWrite API 是微软设计糟糕的 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

于 2013-05-09T09:03:52.447 回答