前提
Azure上の仮想マシン(Windows)にリモートデスクトップ接続することを考えています。
この時に、詳しくは説明できないのですが、ちょっと理由があって、ポート番号を変換して接続することを検討しています。
以下の方式で接続しようと思っています。
【Microsoft リモートデスクトップ (mstsc.exe)】
|
|127.0.0.1:13389に接続。
↓
【今から開発するプログラム】
|
|Azure VM:3389に接続。
↓
【Azure VM】
【今から開発するプログラム】は、C#での開発を考えています。
TcpListenerクラスで、mstsc.exeから送信されデータを全て受け取り、
受け取ったデータをTcpClientクラスで、Azure VMに送信するという方針で作ろうと思いました。
質問内容
上記のような方針で作ってみたのですが、全くRDP接続できなくて困っています。
そもそもの方針が間違っている可能性も含めて、どうしたらいいか考えています。
どのようにすれば、上記のようなプログラムを作ることができるでしょうか?
C#/Windowsという条件は変えることができません。
発生している問題・エラーメッセージ
RDPが発するエラーメッセージは以下の通りです。
内部エラーが発生しました。
また、後述のプログラムで出力したデバッグメッセージは以下の通りです。
*** リモートデスクトップ(mstsc.exe)から、19バイトのデータを読み取りました。 *** 19バイトのデータを送信。(本プログラム -> サーバー) *** クライアント -> 本プログラム -> サーバーへのデータ送信完了 *** サーバーから、19バイトのデータを読み取りました。 *** 19バイトのデータをクライアント(mstsc.exe)に送信しました。 *** サーバー -> 本プログラム -> クライアントへのデータ送信完了 *** リモートデスクトップ(mstsc.exe)から、47バイトのデータを読み取りました。 *** 47バイトのデータを送信。(本プログラム -> サーバー) *** クライアント -> 本プログラム -> サーバーへのデータ送信完了 *** サーバーから、19バイトのデータを読み取りました。 *** 19バイトのデータをクライアント(mstsc.exe)に送信しました。 *** サーバー -> 本プログラム -> クライアントへのデータ送信完了 *** リモートデスクトップ(mstsc.exe)から、47バイトのデータを読み取りました。 *** 47バイトのデータを送信。(本プログラム -> サーバー) *** クライアント -> 本プログラム -> サーバーへのデータ送信完了 *** サーバーから、19バイトのデータを読み取りました。 *** 19バイトのデータをクライアント(mstsc.exe)に送信しました。 *** サーバー -> 本プログラム -> クライアントへのデータ送信完了
該当のソースコード
C#
1using System; 2using System.Collections.Generic; 3using System.Diagnostics; 4using System.Linq; 5using System.Net; 6using System.Net.Sockets; 7using System.Text; 8using System.Threading.Tasks; 9using System.Windows; 10using System.Windows.Controls; 11using System.Windows.Data; 12using System.Windows.Documents; 13using System.Windows.Input; 14using System.Windows.Media; 15using System.Windows.Media.Imaging; 16using System.Windows.Navigation; 17using System.Windows.Shapes; 18 19namespace WpfApp1 20{ 21 /// <summary> 22 /// MainWindow.xaml の相互作用ロジック 23 /// </summary> 24 public partial class MainWindow : Window 25 { 26 private TcpListener tcpListener; 27 private const int rdpPortNumber = 3389; 28 private const int localRdpPortNumber = 13389; 29 private const string virtualMachine = "<< Azure 仮想マシンのIPアドレス >>"; 30 31 public MainWindow() 32 { 33 InitializeComponent(); 34 } 35 36 private void Window_Loaded(object sender, RoutedEventArgs e) 37 { 38 if (tcpListener != null) 39 { 40 return; 41 } 42 43 tcpListener = new TcpListener(IPAddress.Parse("127.0.0.1"), localRdpPortNumber); 44 tcpListener.Start(); 45 46 tcpListener.BeginAcceptTcpClient(TcpClientAccepted, null); 47 } 48 49 private void TcpClientAccepted(IAsyncResult result) 50 { 51 // client : mstsc.exe 52 // bridge : this program. 53 // server : azure virtual machine. 54 using (var clientToBridge = tcpListener.EndAcceptTcpClient(result)) 55 { 56 tcpListener.BeginAcceptTcpClient(TcpClientAccepted, null); 57 58 if (clientToBridge == null) 59 { 60 Debug.WriteLine(" *** clientToBridge == null"); 61 return; 62 } 63 64 using (var clientToBridgeStream = clientToBridge.GetStream()) 65 { 66 using (var bridgeToServer = new TcpClient()) 67 { 68 bridgeToServer.Connect(IPAddress.Parse(virtualMachine), rdpPortNumber); 69 using (var bridgeToServerStream = bridgeToServer.GetStream()) 70 { 71 byte[] buffer = new byte[10240]; 72 // client -> this program -> server という経路でデータを送信する。 73 while (true) 74 { 75 // クライアントプログラムからのデータを読み取る。 76 var length = clientToBridgeStream.Read(buffer, 0, buffer.Length); 77 Debug.WriteLine($" *** リモートデスクトップ(mstsc.exe)から、{length}バイトのデータを読み取りました。"); 78 if (length > 0) 79 { 80 // 本プログラムから Azure Virtual Machine にデータを送信する。 81 bridgeToServerStream.Write(buffer, 0, length); 82 Debug.WriteLine($" *** {length}バイトのデータを送信。(本プログラム -> サーバー)"); 83 } 84 85 if (length < buffer.Length) 86 { 87 Debug.WriteLine($" *** クライアント -> 本プログラム -> サーバーへのデータ送信完了"); 88 break; 89 } 90 } 91 92 // server -> bridge -> client という経路でデータを送信する。 93 while (true) 94 { 95 // サーバーから、本プログラムへのデータを読み取る。 96 var length = bridgeToServerStream.Read(buffer, 0, buffer.Length); 97 Debug.WriteLine($" *** サーバーから、{length}バイトのデータを読み取りました。"); 98 if (length > 0) 99 { 100 clientToBridgeStream.Write(buffer, 0, length); 101 Debug.WriteLine($" *** {length}バイトのデータをクライアント(mstsc.exe)に送信しました。"); 102 } 103 104 if (length < buffer.Length) 105 { 106 Debug.WriteLine($" *** サーバー -> 本プログラム -> クライアントへのデータ送信完了"); 107 break; 108 } 109 } 110 } 111 } 112 } 113 } 114 } 115 } 116} 117
回答2件