终端服务丢弃消息

时间:2013-04-16 17:27:52

标签: remote-desktop terminal-services

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

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

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

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

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

愤怒的编码器的answer是正确的,你必须使用重叠的I / O.我发现一个解决方案在细节上有所不同:

首先,正如我在我的问题中提到的,只要在同一个线程中调用它们,WTSVirtualChannelRead()和WTSVirtualChannelWrite()通常就会起作用。但仍然WTSVirtualChannelRead()偶尔会遗漏消息。显然,解决方法是block for 1 sec。当你需要写时不好,但是当读取阻塞时却不能。

其次,我根据this article在.NET中实现了重叠I / O.使用I / O完成端口,读取和写入总是在回调方法中完成,因此无需区分是否存在可用数据。

第三,没有必要实施动态虚拟通道;每个Virtual Channel Client API的静态通道都可以正常工作。