1

初めてスレッドとソケットを使っているのでチャット(ローカル)をしてみます

ClientA (実際にはサーバー) :

public class ClientA {

    public static void main(String[] args) {

        ServerSocket servsock = null;
        try {
            servsock = new ServerSocket(9998);
            Socket conn = servsock.accept();
            System.out.println("server socket listening on local port : " + servsock.getLocalPort());
            System.out.println("socket listening on local port : " + conn.getLocalPort());
            System.out.println("socket listening on port : " + conn.getPort());
            servsock.close();

            TReadingSock tls = new TReadingSock(conn);
            tls.start();
            TWritingSock tes = new TWritingSock(conn);
            tes.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

クライアント B、実際のクライアント:

public class ClientB {

    public static void main(String[] args) {

        Socket sock = null;
        try {
            sock = new Socket("localhost", 9998);
            System.out.println("socket listening on local port : " + sock.getLocalPort());
            System.out.println("socket listening on port : " + sock.getPort());
        } catch (IOException e) {
            e.printStackTrace();
        }

        TReadingSock tls = new TReadingSock(sock);
        tls.start();
        TWritingSock tes = new TWritingSock(sock);
        tes.start();
    }
}

印刷ショーこれ:

クライアントA:

server socket listening on local port : 9998
socket listening on local port : 9998 
socket listening on port : 50875

クライアント B:

socket listening on local port : 50875  
socket listening on port : 9998

ばかげているように見えますが、ソケット全体を理解するのに深刻な問題があります。ここで得られるのは、プログラムが異なるポートでリッスンしているということだけです。理由はわかりません。一部の人にとってはかなり明白に見えるに違いないと思うので、私を啓発するためにあなたの助けを求めています!

前もって感謝します。

編集:すべての回答に感謝します。問題は、ポートをリッスンし、接続しようとしているクライアントを受け入れるために ServerSocket が必要なことです。完了すると、Socket オブジェクトが返されます。これをスレッドに渡して、スレッドがジョブを実行できるようにします。これは ClientA 用です。クライアント B はソケットを作成するだけで、9998 ポートに接続しようとします。これは、私が ServerSocket でリッスンしているポートです。次に、それをスレッドに渡します。問題は、クライアント (A から B) を起動し、コンソール A で書き込みを行うと、コンソール B では何も起こらないことです (おそらく、以前に指定する必要があったかもしれません、申し訳ありません)。

ソケットが使用しているポートが原因だと思いました。いくつかのチュートリアルを確認しましたが、あなたの回答を読んだ後でも、何が問題なのかわかりません. 念のため、スレッドの内容を投稿します。

public class TWritingSock extends Thread {
    private Socket sockw;

    public TWritingSock(Socket sockw){
        this.sockw = sockw;
    }

    @Override
    public void run(){
        try {
            while(true){
                //Recuperation des saisies clavier
                BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

                //Ecriture de la saisie
                PrintWriter pw= new PrintWriter(sockw.getOutputStream(), true);

                String typed = br.readLine();
                if(typed.equals("fin")){
                    //sockw.close();
                    System.out.println("fermé");
                    break;
                }
                pw.write(typed);
            }           
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                sockw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    } 
}

public class TReadingSock extends Thread {
    private Socket sockr;

    public TReadingSock(Socket sockr){
        this.sockr = sockr;
    }

    @Override
    public void run(){
        try {
            while(true){
                BufferedReader br = new BufferedReader(new InputStreamReader(sockr.getInputStream()));
                String typed = br.readLine();
                if(typed.equals("fin")){
                    //sockr.close();
                    System.out.println("fermé");
                    break;
                }
                System.out.println(typed);
            }   
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                sockr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
4

3 に答える 3

2

(ソケットについて説明するために粗雑で単純なイメージを使用します。これをできるだけ簡単に説明する試みとして参照してください。)

ソケットをトンネルと見なします。さて、トンネルの終わりが 9998 であると言ったら、あなたはそこにたどり着くことができますが、このトンネルの終わりは何でもかまいません。決めるのはあなた次第です。

ClientA (実際にはサーバー) は、「ポート 9998 でリッスンしたい」と言っています。ClientA が接続すると、「OK 接続されました。私はポート 9998 に、あなたは 50875 にいます。」.

ClientB は、「ポート 9998 にアクセスしたいので、ポート 50875 を使用します」と言っています。

どちらのアプリケーションも、トンネルの行き先を認識しているため、トンネル経由で通信できるようになりました。

于 2013-05-29T14:01:00.390 に答える
1

インターネット上の各 TCP 接続は、エンドポイント A の IP アドレス、エンドポイント A のポート番号、エンドポイント B の IP アドレス、エンドポイント B のポートという 2 つのペア、つまり 4 つの要素で構成されています。トランスポート レベルでは、アドレスはIP パケット ヘッダーで指定され、ポートはTCP ヘッダーで指定されます。これにより、パケットの配信先のホストとプロセスを (ポート経由で) 明確に識別することができます。

「サーバー」ソケットをリッスンするときはbind()、そのエンドポイントのポート番号(あなたの場合は9998)を修正します。クライアント接続が到着すると、他の 3 つの部分も固定されます。ローカル IP は、接続が到着したネットワーク インターフェイスのものであり、リモート IP とポートは接続クライアントのものです。ポートは通常、OS によって選択されます。一時ポートのプール、例では 50875 。

于 2013-05-29T14:05:41.827 に答える
0

わかりました、概念を理解できるように簡単にしましょう。そのため、チュートリアルを読むとすべてが理にかなっています。

ソケットは非常に簡単に言えば、クライアントとサーバー間のトンネルです。一方が読み取ると、もう一方が書き込みます。言い換えれば、一方が読み取りを待機しているときに、もう一方がトンネルに書き込みます。読み取りが成功すると、受信側でデータを処理できます。

ここでは、クライアントとサーバーの両方が双方向通信を行うことができます。一部の人々は、ジグザグのようなパターンを作成し、サーバーが読み取りを待機し、クライアントがデータを送信して読み取り待機に入り、サーバーがそれを処理してクライアントに応答します。クライアントは成功/エラーを表示します。などなど。

読み取りと書き込みを行う前に、接続を形成します。接続を形成するには、自分の ID (IP アドレス/DNS) が何であるかを互いに伝える必要があります。

ここまでできた?

ポートについて説明する必要がある場合はお知らせください。

于 2013-05-29T14:01:29.890 に答える