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

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

ただいまの
回答率

91.36%

  • Java

    10453questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

スレッドを使ったチャットプログラムで送信したテキストが相手のものとして返ってきてしまう

解決済

回答 1

投稿 2017/12/02 14:05

  • 評価
  • クリップ 1
  • VIEW 54

kmmtprgm

score 2

javaを用いてスレッドとソケットを使ったチャットプログラムを作っています。
イメージ説明
目標とする動作は、テキストをSendボタンを押して送信したら引数で指定した相手の画面に表示する、なんですが自分で送ったテキストが自分の画面に表示されて相手の画面には表示されません。どのように書き直せばいいでしょうか

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class SocketChat extends JFrame implements Runnable,ActionListener{
    // GUI関係の変数
    JPanel panel;
    Container cont;
    JMenuBar menuBar;
    JMenu menu;
    JTextField tf;
    JTextArea resArea;
    JScrollPane area;
    JButton send;
    JMenuItem menuConnect;
    JMenuItem menuDisconnect;

    // 通信関係の変数
    String connectHost;
    int connectPort;
    int port;
    int myPort;
    ServerSocket serverSocket;
    Socket socket = null;
    PrintWriter pw;
    BufferedReader br;

    public SocketChat(String title, String host, int port, int myPort) {
        super(title);
        initGUI();
        // 通信関係の初期化
        this.connectHost = host; // 相手のホスト名
        this.connectPort = port; // 相手のポート番号
        this.myPort = myPort; // 自分のポート番号
    }

    public static void main(String[] args) {
        if(args.length!=3){
            System.out.println("使用方法 : java SocketChat 相手ホスト名 相手ポート番号 自分のポート番号");
        }else{
            SocketChat schat = new SocketChat("SocketChat", args[0], Integer.parseInt(args[1]), Integer.parseInt(args[1]));
            //SocketChat schat = new SocketChat("SocketChat");
            schat.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            schat.setSize(350, 300);
            schat.setVisible(true);
            schat.startServer();
        }
    }

    private void initGUI() {
        // パネルの作成とコンテントペインへの貼り付け
        // メニュー
        // 接続メニュー
        // 切断メニュー
        // 入力用テキストエリア
        // スクロールバーつき応答履歴エリア
        // 送信ボタン
        panel = new JPanel();
        panel.setLayout(new BorderLayout());
        cont = getContentPane();
        cont.add(panel);
        menuBar = new JMenuBar();
        setJMenuBar(menuBar);
        menu = new JMenu("Menu");
        menuBar.add(menu);
        menuConnect = new JMenuItem("Connect");
        menuConnect.addActionListener(this);
        menu.add(menuConnect);
        menuDisconnect = new JMenuItem("Disconnect");
        menuDisconnect.addActionListener(this);
        menu.add(menuDisconnect);
        send =new JButton("Send");
        send.addActionListener(this);
        cont.add(send, BorderLayout.SOUTH);
        tf = new JTextField(5);
        panel.add(tf);
        cont.add(tf, BorderLayout.NORTH);
        resArea = new JTextArea();
        panel.add(resArea);
    }

    // サーバ立ち上げと接続待ち
    void startServer() {
        try {
            // サーバソケットの作成
            serverSocket = new ServerSocket(connectPort);
            // SocketオブジェクトからOutputStreamオブジェクトを取得
            socket = serverSocket.accept();
            OutputStream out = socket.getOutputStream();
            // PrintWriterオブジェクトに変換
            pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(out)));
            // SocketオブジェクトからInputStreamオブジェクトを取得
            InputStream in = socket.getInputStream();
            // BufferedReaderに変換
            br = new BufferedReader(new InputStreamReader(in));
            // スレッドのスタート
            Thread th = new Thread(this);
            th.start();
        } catch(IOException e) { e.printStackTrace(); }
    }

    // スレッドの仕事内容
    public void run() {
        try {
            String input;
            // 受信データを行単位で書き出す
            while((input = br.readLine()) != null) {
                synchronized(resArea) {
                    resArea.append("相手: " + input + "\n");
                    //System.out.println("Received");
                }
            }
        } catch(IOException e) { e.printStackTrace(); }

        // 通信が終了した場合
        resArea.append(socket.getInetAddress().getHostName() + "との接続を終了しました\n");
    }

    void sendActionPerformed(ActionEvent e) {
        synchronized(resArea) {
            // 入力データを取得
            String message = this.tf.getText();
            try {
                pw.println(message);
                pw.flush();
            } catch(Exception ex) { ex.printStackTrace(); }
            // 送信したデータを自分の画面にも表示
            if(!message.equals("")){
                resArea.append("自分: " + message + "\n");
            }
            tf.setText(null);
        }
    }

    // 接続メニューが選択されたとき
    void connectActionPerformed(ActionEvent e) {// 接続要求
        try {
            // クライアントソケットの作成 ホスト名を"127.0.0.1"としてもよい
            socket = new Socket(connectHost,connectPort);
            // SocketオブジェクトからOutputStreamオブジェクトを取得
            OutputStream out = socket.getOutputStream();
            // PrintWriterオブジェクトに変換
            pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(out)));
            // SocketオブジェクトからInputStreamオブジェクトを取得
            InputStream in = socket.getInputStream();
            // BufferedReaderに変換
            br = new BufferedReader(new InputStreamReader(in));
            this.resArea.append(connectHost + ":" + connectPort + "に接続しました" + "\n");

            Thread th = new Thread(this);
            th.start();
        } catch(Exception ex) { ex.printStackTrace(); }
    }

    void disConnectActionPerformed(ActionEvent e) { // 切断要求
        try {
            pw.close();
            br.close();
            socket.close();
        } catch(Exception ex2) { ex2.printStackTrace(); }
    }

    public void actionPerformed(ActionEvent e) {
        if(e.getSource()==send){
            sendActionPerformed(e);
        }else if(e.getSource()==menuConnect){
            connectActionPerformed(e);
        }else if(e.getSource()==menuDisconnect){
            disConnectActionPerformed(e);
        }
    }
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

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

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

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

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

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

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

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

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

serverSocket = new ServerSocket(connectPort);

接続待ちも接続先も同じポートを指定しているので自分に送ることになりますね。
接続待ちに使うポートはmyPortの指定の方ですね。
serverSocket = new ServerSocket(myPort);

投稿 2017/12/02 15:01

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/02 15:27

    自分のポート番号に相手のポート番号を代入していたのも原因でした。ありがとうございました!

    キャンセル

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

ただいまの回答率

91.36%

関連した質問

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

  • Java

    10453questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • トップ
  • Javaに関する質問
  • スレッドを使ったチャットプログラムで送信したテキストが相手のものとして返ってきてしまう