実現したいこと
今の状況を具体的な例を上げて言うと
2台のPCを準備して片方のPC(以後PC1と呼ぶ)にサーバーとしての役割をプログラミングで言うメソッドのように扱おうとしています。
もう片方のPC(以後PC2と呼ぶ)からTCP通信を用いて適当な値をPC1に送信します。
PC1はPC2から受け取った値を用いて特定の処理をして計算結果をPC2に返します。
このPC2から送る値を引数とするとPC1から返ってくる値が戻り値のようでひとつのメソッドの用に感じました。
現在、PC1をサーバーとして扱うのでPC1のあるグローバルIPアドレスのドメインを取得、DDNSの設定、プライベートIPアドレスの固定、そのIPアドレスにポート開放をすることでPC1にPC2からデータを送ることはできました。PC2も同様にPC1と同じ手順を追ってPC1からPC2へデータを送ることもできたのですがここで問題及び今回の質問の主題が発生しました。
発生している問題・分からないこと
この方法ではPC1からPC2に通信するときもPC2が位置するグローバルIPアドレスを把握してそのポート開放をする必要があります。ですが普段他のアプリケーションを使用するとき、例えばWebブラウザでWebページのアクセスするときは内部で相手サーバー側のポート番号を把握していたとしてもこちらは特段ポート開放していませんし(ルーターの設定)、IPアドレスへポートフォワーディングしてもいません。なのに情報が受信できると言うことはこちらが相手のポート番号を知ってたりする場合一時的に送受信できるトンネルがあると予想しました。(TCP通信の性質上、接続完了の情報をサーバーがクライアントに送り返すのもあったので)(最初はこちらが相手サーバー側に一時的にポート開放しその番号を送信しているのかと思いましたがポート開放するにはルーターやONUのパスワードが必要になるので除外しました。)
まとめるとPC2からPC1への通信を始めたときにPC1からPC2へデータを送り返すときPC2がポート開放をせずに受け取る方法を知りたいです。
下のソースコードだと一方方向の通信なので返信をしたいのですがこのとき可能ならばESTABLISHとなったSocketを使ってPC2側(Client.java)は受け取るポートを新たに指定せずに受信したいです。
該当のソースコード
import java.io.DataInputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class Server { ServerSocket svSock; public Server(int port) { try { //サーバーのポート番号を指定 svSock = new ServerSocket(port); svSock.setSoTimeout(0); } catch (IOException e) { throw new RuntimeException(e); } } public int getID() { try { //アクセスを待ち受け Socket sock = svSock.accept(); //受信ストリームの取得(DataInputStreamでラップ) DataInputStream in = new DataInputStream(sock.getInputStream()); //int型データを受信 int getID = in.readInt(); //受信データの表示 System.out.println("「" + getID + "」を受信しました。"); //受信ストリームの終了 in.close(); /* //サーバー終了 svSock.close(); */ return getID; } catch (IOException e) { e.printStackTrace(); return 0; } } }
import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; public class Client { public Client(String hostname, int port, int sendID) { try { //送信先のIPアドレス(ドメインなどの名前)とポートを指定 Socket sock = new Socket(hostname, port); //送信ストリームの取得 DataOutputStream out = new DataOutputStream(sock.getOutputStream()); /* //文字列をUTF-8形式のバイト配列に変換して送信 out.write(sendData.getBytes("UTF-8")); */ out.writeInt(sendID); //送信データの表示 System.out.println("「" + sendID + "」を送信しました。"); //送信ストリームを表示 out.close(); //終了 sock.close(); } catch (IOException e) { e.printStackTrace(); } } }
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
参考にしたサイトを並べておきます。
【Java】TCP通信を利用したデータ送受信
JavaでTCP通信によるデータ送受信
補足
特になし
