質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

解決済

TCP接続を行う際、ポート番号を変換するプログラムを作りたい

rarirurero3421
rarirurero3421

総合スコア1

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

2回答

0評価

0クリップ

614閲覧

投稿2022/07/16 12:14

前提

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#

using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace WpfApp1 { /// <summary> /// MainWindow.xaml の相互作用ロジック /// </summary> public partial class MainWindow : Window { private TcpListener tcpListener; private const int rdpPortNumber = 3389; private const int localRdpPortNumber = 13389; private const string virtualMachine = "<< Azure 仮想マシンのIPアドレス >>"; public MainWindow() { InitializeComponent(); } private void Window_Loaded(object sender, RoutedEventArgs e) { if (tcpListener != null) { return; } tcpListener = new TcpListener(IPAddress.Parse("127.0.0.1"), localRdpPortNumber); tcpListener.Start(); tcpListener.BeginAcceptTcpClient(TcpClientAccepted, null); } private void TcpClientAccepted(IAsyncResult result) { // client : mstsc.exe // bridge : this program. // server : azure virtual machine. using (var clientToBridge = tcpListener.EndAcceptTcpClient(result)) { tcpListener.BeginAcceptTcpClient(TcpClientAccepted, null); if (clientToBridge == null) { Debug.WriteLine(" *** clientToBridge == null"); return; } using (var clientToBridgeStream = clientToBridge.GetStream()) { using (var bridgeToServer = new TcpClient()) { bridgeToServer.Connect(IPAddress.Parse(virtualMachine), rdpPortNumber); using (var bridgeToServerStream = bridgeToServer.GetStream()) { byte[] buffer = new byte[10240]; // client -> this program -> server という経路でデータを送信する。 while (true) { // クライアントプログラムからのデータを読み取る。 var length = clientToBridgeStream.Read(buffer, 0, buffer.Length); Debug.WriteLine($" *** リモートデスクトップ(mstsc.exe)から、{length}バイトのデータを読み取りました。"); if (length > 0) { // 本プログラムから Azure Virtual Machine にデータを送信する。 bridgeToServerStream.Write(buffer, 0, length); Debug.WriteLine($" *** {length}バイトのデータを送信。(本プログラム -> サーバー)"); } if (length < buffer.Length) { Debug.WriteLine($" *** クライアント -> 本プログラム -> サーバーへのデータ送信完了"); break; } } // server -> bridge -> client という経路でデータを送信する。 while (true) { // サーバーから、本プログラムへのデータを読み取る。 var length = bridgeToServerStream.Read(buffer, 0, buffer.Length); Debug.WriteLine($" *** サーバーから、{length}バイトのデータを読み取りました。"); if (length > 0) { clientToBridgeStream.Write(buffer, 0, length); Debug.WriteLine($" *** {length}バイトのデータをクライアント(mstsc.exe)に送信しました。"); } if (length < buffer.Length) { Debug.WriteLine($" *** サーバー -> 本プログラム -> クライアントへのデータ送信完了"); break; } } } } } } } } }

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

KOZ6.0

2022/07/16 20:05 編集

ご提示のコードでは一回受送信して終わりに見えますが、どちらかから切断されるまで受送信を繰り返す必要があるはずです。

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。