Windows 7 NetMeeting
在 Windows 7 系统之间共享桌面。
引言
Windows XP 中简单易用的桌面共享应用程序“Netmeeting”在 Windows 7 中被移除。它被 Vista 中的“会议场所”取代,并在 Windows 7 中完全删除。迁移到 Windows 7 后,我几乎每周至少会感到需要它一次,所以我开始在 Windows 7 中实现桌面共享应用程序。
背景
该桌面共享应用程序基于以下两个概念构建:
- 使用 WCF 进行通信;以及
- 使用远程桌面 API 进行桌面共享。
1. 使用 WCF 进行通信
WCF 用于维护客户端和服务器之间的通信。服务器将消息广播给所有已连接的客户端。我使用 TCP/IP 协议中的回调机制来实现从服务器到客户端的消息发送。
代码逻辑
该应用程序将托管一个 WCF 服务。IMMService
的 ServiceContract
和回调接口如下所示:
[ServiceContract(SessionMode = SessionMode.Required,
CallbackContract = typeof(IServerCallbackToClient))]
public interface IMMService
{
[OperationContract(IsOneWay = true, IsInitiating = true, IsTerminating = false)]
void Say(Person person, String msg, MessageType MsgType);
[OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
void Whisper(string to, String msg);
[OperationContract(IsOneWay = false, IsInitiating = true, IsTerminating = false)]
Person[] Subscribe(Person name);
[OperationContract(IsOneWay = false, IsInitiating = false, IsTerminating = true)]
bool Unsubscribe(Person name);
}
- 函数
Say
将消息发送到服务器,服务器再将消息广播给所有已连接的客户端。 - 函数
Whisper
将消息发送到服务器进行某些操作。该消息不会被广播。 - 函数
Subscribe
和Unsubscribe
用于加入和离开会议组。
public interface IServerCallbackToClient
{
[OperationContract(IsOneWay = true)]
void Receive(Person sender, String message, MessageType MsgType);
[OperationContract(IsOneWay = true)]
void ReceiveWhisper(Person sender, string message);
[OperationContract(IsOneWay = true)]
void UserEnter(Person person);
[OperationContract(IsOneWay = true)]
void UserLeave(Person person);
}
函数 Receive
是服务器到客户端的回调,用于通知消息已接收,以及对其他操作的相同确认。回调通道存储在服务器的 subscribe
函数中。Receive
将使用这些回调通道将消息回调给所有客户端。
用户的相关数据从客户端和服务器传递。类 Person
包含这些数据。
[DataContract]
public class Person : INotifyPropertyChanged
{
private string imageURL;
private string name;
public event PropertyChangedEventHandler PropertyChanged;
public Person()
{
}
public Person(string imageURL, string name)
{
this.imageURL = imageURL;
this.name = name;
}
[DataMember]
public string ImageURL
{
get { return imageURL; }
set
{
imageURL = value;
OnPropertyChanged("ImageURL");
}
}
[DataMember]
public string Name
{
get { return name; }
set
{
name = value;
OnPropertyChanged("Name");
}
}
protected void OnPropertyChanged(string propValue)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propValue));
}
}
}
此服务的实现将作为服务器,基本上充当一个 Messenger 服务器。客户端将使用 Subscribe(Person p)
登录。类 Person
包含各个系统的相关数据。订阅后,组内任何人的任何消息都将被广播给组内的其他人。Service
调用 Receive()
函数将消息发送给所有已连接的客户端。
2. 使用远程桌面 API 进行桌面共享
远程桌面 API 用于将桌面广播给所有已连接的客户端。
Using the Code
类 RDPSession
用于共享桌面。当桌面共享时,它会生成一个邀请 string
。桌面查看器需要此邀请 string
才能查看共享的桌面。
m_pRdpSession.OnAttendeeConnected +=
new RDPCOMAPILib._IRDPSessionEvents_OnAttendeeConnectedEventHandler
(OnAttendeeConnected);
m_pRdpSession.OnAttendeeDisconnected +=
new RDPCOMAPILib._IRDPSessionEvents_OnAttendeeDisconnectedEventHandler
(OnAttendeeDisconnected);
m_pRdpSession.OnControlLevelChangeRequest +=
new RDPCOMAPILib._IRDPSessionEvents_OnControlLevelChangeRequestEventHandler
(OnControlLevelChangeRequest);
m_pRdpSession.Open();
IRDPSRAPIInvitation pInvitation = m_pRdpSession.Invitations.CreateInvitation
("DesktopShareServer", "Internal", "", 5);
string invitationString = pInvitation.ConnectionString;
当其中一个系统共享桌面时,生成的邀请 string
将广播给其他人。然后可以使用邀请 string
来查看桌面。
pRdpViewer.Connect(ConnectionString, "Viewer1", "");
pRdpViewer.Dock = DockStyle.Fill;
pRdpViewer.SmartSizing = true;
关注点
由于使用了远程桌面来共享桌面,因此刷新率比 VNC 或 RADMIN 更快,并且对 CPU 的负担也更小。
历史
- 2011 年 4 月 20 日:初始发布。