8

自宅のコンピューターからオフィスのコンピューターへの TCP 接続を確立する必要があります。

オフィスには、複数のコンピューターが接続されているルーターがあります。そのルーターにはインターネットがあるため、そのルーターに接続されているすべてのコンピューターにもインターネットがあります。私の家には、インターネットにアクセスできるコンピューターがあります。オフィスのコンピューターがサーバーとして機能し、自宅のコンピューターがサーバーに接続する必要があります。以前は、サーバー上のポート転送トラフィックによって次のように接続できました。

    NATUPNPLib.UPnPNATClass upnpnat;
    NATUPNPLib.IStaticPortMappingCollection mappings;

    public ServerExample()
    {
        InitializeComponent();

        upnpnat = new NATUPNPLib.UPnPNATClass();
        mappings = upnpnat.StaticPortMappingCollection;

        //                           server local IP address
        mappings.Add(1300, "TCP", 1300, "192.168.150.146", true, "plsease work");
        // this code tels the router to forward all tcp traffic comming from port
        // 1300 to the server computer (it's lan ip address happens to be 192.168.150.146)
        //...

自宅から接続できました。(簡単な方法は、オフィスのルーターのポートを開き、それらを自分のコンピューターに転送することです。問題は、オフィスのルーターにアクセスできないことです)

現在、彼らは私のオフィスのルーターを新しいルーターに交換しましたが、コードを使用できません。新しいルーターを使用して、前のコードを実行すると、次のようになります。

ここに画像の説明を入力

マッピングは null を返すことに注意してください。したがって、マッピングを追加できません。

オフィスの一部の人々は、たとえばライムワイヤーやビットトレントを使用しているため、接続を確立する方法があるはずです。私の問題はおそらく許可に関係していると思いますか?どうすればこれを解決できますか?


編集

調査の結果、私がやろうとしているのは「ファイアウォールへのUDPパンチホール」であることがわかりました。私は実際にtcp接続でそれをやりたいです。tcp と upd の puch holing の違いが何であるかわかりません.... つまり、クライアントがルーターで構成を行うことなくナシを見つけることができるようにすることです。

.

.

.

.

.

.

アップデート

わかりましたので、皆さんがこの質問に投稿したことをc#で試してみたと思います:わかりました、私がしたことをお見せしましょう:

これから説明する内容を理解するには、この図を参照する必要があるかもしれません。 ここに画像の説明を入力

ご存知のように、コンピューター A とコンピューター B の間に tcp 接続を確立したいと考えています。これを行う方法は、tcp パンチホールと呼ばれるものを使用することです。

ステップ 1: 最初に、サーバー S で新しい接続のリッスンを開始します。

                   TcpListener server = new TcpListener(System.Net.IPAddress.Parse(“192.168.11.109”), 55550);
                   Server.Start();

                   var client = server.AcceptSocket();  \\ wait here until someone connects

ステップ 2: 次のようにコンピューター A を使用してサーバーに接続します。

          TcpClient tcpClient = new TcpClient("192.168.11.109", 55550);

ステップ 3: コンピューター A でステップ 2 のコードを実行した後、サーバー S のデバッグは次のようになります。

ここに画像の説明を入力

ステップ 4: ここでの目標は、コンピューター B からコンピューター A に接続することです。サーバー S には、接続を確立するために B が必要とする情報があります。実際には、コンピューター B とサーバー S の間に接続を確立して、B が A に接続するためにサーバー S が B に適切なパラメーターを与えることができるようにする必要があります。

ステップ 5: デバッグ中なのでパラメーターを確認できるので、ポート 3313 でリッスンしてコンピューター A をサーバーにします。すべてのパッケージがルーターに送信されるため、コンピューター A がそのポート (3313) でリッスンするようにします。ポート 3313 の X をコンピューター A に送信する必要があります。

       \\ COMPUTER A 
       TcpListener server = new TcpListener(System.Net.IPAddress.Parse("192.168.0.120"), 3313);
        server.Start();

        var newClient = server.AcceptSocket();  \\ wait here until a client gets connected

ステップ 6: これで、コンピューター A はポート 3313 で新しい接続をリッスンするようになります。ポート 3313 は重要です。これは、ルーター x がそのポートから受信したすべてのパッケージをコンピューター A に転送する必要があるためです。

コンピュータ A は新しい接続を待っています。 ここに画像の説明を入力

ステップ 7: それでは早速!コンピューター B からの接続を確立したいと考えています。実際にはサーバー S がパラメーターを渡しますが、これを機能させようとしているだけなので、コンピューター B でプログラムをすばやく作成します。

          TcpClient tcpClient = new TcpClient(“192.168.11.108”, 3313);
           \\192.168.11.108  is the address of router X

ついに:

何らかの理由で、コンピューター B がコンピューター A に接続できません。

ここに画像の説明を入力

接続できない理由は、ルーター X がパッケージをコンピューター A に転送しなかったためです (ルーター X のポート 54540 でポート転送を有効にしており、そのポートを使用すると機能するため、これを知っています)。ルーター X がポート 3313 からのトラフィックをコンピューター A に転送しなかった理由がわかりません。コンピューター A は既にサーバー S への接続を確立しており、サーバー S がポート 3313 を介してルーター X に送信したすべてのものがコンピューター A に送信されました。ポート 3313 を介してルーター X にパッケージを送信すると、コンピューター A によって受信されない!?

PS:

ここで示したものはすべて、実際には 3 つのルーター X、Y、Z があり、サーバー S、コンピューター A、コンピューター B もあることに注意してください。

ここに画像の説明を入力

4

4 に答える 4

4

TCPホールパンチングは頻繁に機能しません。最善の策は、UDPホールパンチングに固執することです。TCPのような動作が必要な場合は、TCPの動作を提供するRDPまたは同様のプロトコルを使用できますが、トランスポートとしてUDPを使用できます。

もう1つのアプローチは、サーバーを介してすべてのトラフィックを中継することです。各ホストはサーバーに接続でき、サーバーは1つの接続から別の接続にトラフィックをコピーできます。

最善の解決策は、ポート転送やUPnPなどのルーターから何らかのサポートを受けることができる場合です。

于 2011-09-05T19:42:25.740 に答える
4

新しい作業用ルーターはおそらくUPnP無効になっているため、null 参照です。

これがないと、ルーターはインバウンド パケットの送信先を認識できないため、サーバーをインバウンド トラフィックから見えるようにすることはできません。この場合、ルーターは、サーバーへの着信トラフィックをブロックするファイアウォールとして機能します。

これを回避する基本的な方法は次のとおりです。

1) UPnP を開く

これにより、アプリケーションは、インバウンド トラフィックをサーバーに転送する方法をルーターに指示できます。

2) ポートフォワーディングを設定する

上記のように、ルーターを手動で構成します。

3) 作業サーバーをクライアントにする

ルーターは、アウトバウンド接続が接続を開始できるようにすることで機能します。リターン アドレスを記憶し、外部から見える IP を書き換え、外部トラフィックがトーク バックするための未使用のポートを提供します (NAT)。これにより、アウトバウンド要求が外部との通信を確立し、ファイアウォールをバイパスできるようになります。ホーム IP が固定されている場合は、(サーバーを起動して接続を確立できるまで) スケジュールに従ってホームに電話をかけようとするクライアントを職場にセットアップできます。

4) P2P (仲介サーバー) を使用する

どこから始めればよいかわかりませんが、原則は次のとおりです。通常、単一の UDP ポートで動作します。接続の確立には、NAT の背後にないサーバーが使用されます。クライアントは IP を UDP パケットでサーバーに送信し、ルーターは UDP ヘッダーをルーターのリターン アドレスで書き換えます。サーバーはこのデータを受け取り、他のピアに送信します。全員がお互いの返信アドレスを知っているので、TCP トラフィックを直接お互いに送信でき、サーバーは邪魔になりません。

ここには、NAT の基本に関する非常に優れた記事があり、簡単な言葉で説明されています。また、 P2P が NAT を利用してファイアウォールをバイパスする方法を説明しているこちらの優れた記事もあります。

これがあなたにいくつかのアイデアを与えることを願っています。

于 2011-09-04T00:38:01.020 に答える
2

独自のプロキシを作成できます。

サーバー:1300でAからの接続をリッスンし、1301でBからの接続をリッスンします。両方の接続のリストを保持します。それぞれが少なくとも1つある場合は、プロキシオブジェクトを作成します。この時点で、接続があることをBから接続に通知します。これは、信号バイトまたはポート、さらには接続するアドレスである可能性があります。その後、Aからデータを取得したら、Bに送信します。Bからデータを取得したら、Aに送信します。

コンピューターB:プログラムはサーバーのポート1301への接続を維持します。接続が切断された場合は、再確立してください。信号を受信したら(アドレスとポートを持っているか、単に「接続があります」バイトである可能性があります)、目的のポートへの接続を作成し、2つの接続をプロキシオブジェクトに保存します。一方からデータを受信したら、もう一方に送信します。その接続を使用しているので、サーバーのポート1301への新しい接続を確立して、さらに処理します。

もちろん、切断された接続を処理する必要があります。Bとサーバーの間で常に開いている保留中の接続の間にキープアライブ信号を送信すると役立ちます。

これは、プロキシを実行するために私がずっと前に書いたサンプルクラスです。クリーンアップする時間がありませんが、接続を受け入れる親クラスであるTcpProxyが表示されている場合は、Clientが受け入れられた接続であり、RemoteEndPointが接続するエンドポイントです。また、データをファイルに書き込み、無視できる他の処理を実行します。

于 2011-09-06T21:12:00.267 に答える
2

UDP および TCP ホール パンチング テクニックに関する優れた記事があります。

http://www.brynosaurus.com/pub/net/p2pnat/

ただし、このホールパンチング手法には有名なランデブーサーバーが必要であり、セットアップする必要はないと思います。

ところで、オフィスに独自のサーバーを設置することに関する会社のポリシーを再確認する必要があります。セキュリティのために、会社は従業員が自分のサーバーを社内に設置することを許可していないと思います。

于 2011-09-04T07:54:40.063 に答える