# C#(RdpSession) + aardio(RdpViewer)实现桌面共享,并使用代理实现跨网段连接

以下

使用【RdpViewer】称呼共享客户端,【RdpSession】称呼共享服务端

使用【你的程序】称呼共享服务端的启动程序

1、C# RDPSession

添加COM引用 rdpcomapi 1.0 Type Library

C#
session = new RDPSession();
session.OnAttendeeConnected += Session_OnAttendeeConnected;
session.Open();

//对于多对多,也就是当存在多个共享服务端,应使用不通的GroupName,在连接失败需要使用代理连接时才能分辨要连接哪个共享服务端
IRDPSRAPIInvitation invitation = session.Invitations.CreateInvitation(null, "snltty", "snltty", 1024);
string invitationString = invitation.ConnectionString;

//为了能在连接失败后自动连接到代理服务,我们在这里给连接串添加上代理服务器地址
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(invitationString);
XmlElement newLNode = xmlDoc.CreateElement("L");
//假设代理服务地址是192.168.1.18:1803
newLNode.SetAttribute("P", "1803");
newLNode.SetAttribute("N", "192.168.1.18");//我尝试过,rdpviewer不会连接127.0.0.1,请使用局域网IP
xmlDoc.DocumentElement["C"]["T"].AppendChild(newLNode);
invitationString = xmlDoc.OuterXml;

//invitationString 可以把连接串通过各种方式发送给对方

private void Session_OnAttendeeConnected(object pAttendee)
{
    //只给查看权限
    IRDPSRAPIAttendee attendee = (IRDPSRAPIAttendee)pAttendee;
    attendee.ControlLevel = CTRL_LEVEL.CTRL_LEVEL_VIEW;
}

2、aardio RdpViewer

c#可以直接用 RdpViewer控件

C#
import com.lite;
var dll = com.lite("rdpviewerax.dll");
var tsc = dll.createEmbedEx(mainForm,"{32be5ed2-5c86-480f-a914-0ff8885a1b3f}");
tsc.SmartSizing = true;
tsc.DisconnectedText = "正在连接至共享桌面....";

tsc.OnConnectionFailed = function(){
}
tsc.OnConnectionTerminated = function(){
}
//要填写对应的GroupName
tsc.Connect(invitationString,"snltty","snltty");

3、代理流程

代理是如何让RdpViewerRdpSession形成一条连接,使其成功连接的

  1. RdpViewer 连接代理,得到一个 socket1
  2. 代理去通知你的程序,让它也来连接代理
  3. 你的程序,与代理连接,得到socket2
  4. 你的程序,与RdpSession连接,得到socket3
  5. socket1socket2socket3 之间,交换数据

RdpViewer—socket1—>192.168.1.18:1803<—–socket2<——你的程序—socket3—>RdpSession

3、代理服务

RdpViewer连接前几个地址都无法连接时,会连接我们添加在最后面的代理服务,我们只需要建立一个这样的服务,等待连接

  1. 当代理服务收到连接
  2. 收到第一个数据包,解析出GroupName
  3. 此时你已经有能力构建出一条完整的连接进行数据交换了
  4. 加油

解析GroupName的示例代码

C#
private readonly byte[] endBytes = Encoding.UTF8.GetBytes("\r\n");
private readonly byte[] startBytes = Encoding.UTF8.GetBytes("mstshash=");
private bool GetGroupName(Memory<byte> memory, out string groupName)
{
    groupName= string.Empty;

    int start = memory.Span.IndexOf(startBytes);
    if (start < 0) return false;

    memory = memory.Slice(start);
    int end = memory.Span.IndexOf(endBytes);
    if (end < 0) return false;

    groupName = Encoding.UTF8.GetString(memory.Span.Slice(startBytes.Length, end - startBytes.Length));

    return true;
}