0

ソケットを介してサーバーと 1 つのクライアントの間で機能するインスタント メッセンジャー チャットの作成に関するYouTube シリーズを終了しました。ただし、複数のクライアントが同時に接続できるように、このチャットを改善したいと考えています。

サーバーは正常に動作し、最初のクライアントも正常に動作します。最初に開いたクライアント ウィンドウで、次のメッセージが表示されます。

Attempting connection...
Connected to 127.0.0.1
Streams are now setup!
SERVER - You are now connected!

しかし、開いた 2 番目のクライアント ウィンドウでは、ストリームがセットアップされず、次のメッセージしか表示されません。

Attempting connection...
Connected to 127.0.0.1

この問題を解決するにはマルチスレッドが必要だと聞いたことがありますが、どうすればよいかわかりません。

これらは私のファイルです:

ChatServerTest

import javax.swing.JFrame;

public class ChatServerTest {
    public static void main(String[] args) {
        ChatServer server =  new ChatServer();
        server.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        server.startRunning();
    }
}

チャットサーバー

import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ChatServer extends JFrame {

    private JTextField userText;
    private JTextArea chatWindow;
    private ObjectOutputStream output;
    private ObjectInputStream input;
    private ServerSocket server;
    private Socket connection;

    int port = 1234; // Test port

    //constructor (GUI)
    public ChatServer() {
        super("Instant Messenger (Server)");
        userText = new JTextField();
        userText.setEditable(false);
        userText.addActionListener(
                new ActionListener() {
                    public void actionPerformed(ActionEvent event){
                        sendMessage(event.getActionCommand());
                        userText.setText("");
                    }
                }
            );
        add(userText, BorderLayout.NORTH);
        chatWindow = new JTextArea();
        add(new JScrollPane(chatWindow));
        setSize(300,150);
        setVisible(true);
    }

    //set up and run the server
    public void startRunning(){
        try{
            server = new ServerSocket(port);
            while(true){
                try{
                    waitForConnection();
                    setupStreams();
                    whileChatting();
                }catch(EOFException eofException){
                    showMessage("\nServer ended the connection!");
                }finally{
                    closeCrap();
                }
            }
        }catch(IOException ioException){
            ioException.printStackTrace();
        }
    }

    //wait for connection, then display connection information
    private void waitForConnection() throws IOException{
        showMessage("Waiting for someone to connect... \n");
        connection = server.accept();
        showMessage("Now connected to " + connection.getInetAddress().getHostName());
    }

    //get stream to send and receive data
    private void setupStreams() throws IOException{
        output = new ObjectOutputStream(connection.getOutputStream());
        output.flush();
        input = new ObjectInputStream(connection.getInputStream());
        showMessage("\nStreams are now setup!\n");
    }

    //during the chat conversation
    private void whileChatting() throws IOException{
        String message = "You are now connected!";
        sendMessage(message);
        ableToType(true);
        do{
            try{
                message = (String) input.readObject();
                showMessage("\n" + message);
            }catch(ClassNotFoundException classNotFoundException){
                showMessage("\nERROR: Not a string");
            }
        }while(!message.equals("CLIENT - END"));
    }

    private void closeCrap(){
        showMessage("\nClosing connections...\n");
        ableToType(false);
        try{
            output.close();
            input.close();
            connection.close();
        }catch(IOException ioException){
            ioException.printStackTrace();
        }
    }

    //send a message to client
    private void sendMessage(String message) {
        try{
            output.writeObject("SERVER - " + message);
            output.flush();
            showMessage("\nSERVER - " + message);
        }catch(IOException ioExcenption){
            chatWindow.append("\nERROR: Can't send message");
        }
    }

    //updates chatWindow
    private void showMessage(final String text){
        SwingUtilities.invokeLater(
            new Runnable(){
                public void run(){
                    chatWindow.append(text);

                }
            }
        );
    }

    //let the user type stuff into their box
    private void ableToType(final boolean tof) {
        SwingUtilities.invokeLater(
            new Runnable(){
                public void run(){
                    userText.setEditable(tof);
                }
            }
        );
    }

}

ChatClientTest

import javax.swing.JFrame;

public class ChatClientTest {
    public static void main(String[] args) {
        String IP = "127.0.0.1";
        ChatClient client;
        client = new ChatClient(IP);
        client.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        client.startRunning();
    }
}

チャットクライアント

import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ChatClient extends JFrame {

    private JTextField userText;
    private JTextArea chatWindow;
    private ObjectOutputStream output;
    private ObjectInputStream input;
    private String message = "";
    private String serverIP;
    private Socket connection;

    int port = 1234; // Test port

    //constructor
    public ChatClient(String host){
        super("Instant Messenger (Client)");
        serverIP = host;
        userText = new JTextField();
        userText.setEditable(false);
        userText.addActionListener(
            new ActionListener(){
                public void actionPerformed(ActionEvent event){
                    sendMessage(event.getActionCommand());
                    userText.setText("");
                }
            }
        );
        add(userText, BorderLayout.NORTH);
        chatWindow = new JTextArea();
        add(new JScrollPane(chatWindow), BorderLayout.CENTER);
        setSize(300, 150);
        setVisible(true);

    }

    //connect to server
    public void startRunning(){
        try{
            connectToServer();
            setupStreams();
            whileChatting();
        }catch(EOFException eofException){
            showMessage("\nClient terminated connection.");
        }catch(IOException ioException){
            ioException.printStackTrace();
        }finally{
            closeCrap();
        }
    }

    //connect to server
    private void connectToServer() throws IOException{
        showMessage("Attempting connection...\n");
        connection = new Socket(InetAddress.getByName(serverIP), port);
        showMessage("Connected to " + connection.getInetAddress().getHostName());
    }

    //set up streams to send and receive messages
    private void setupStreams() throws IOException{
        output = new ObjectOutputStream(connection.getOutputStream());
        output.flush();
        input = new ObjectInputStream(connection.getInputStream());
        showMessage("\nStreams are now setup!");
    }

    //while chatting with server
    private void whileChatting() throws IOException{
        ableToType(true);
        do{
            try{
                message = (String) input.readObject();
                showMessage("\n" + message);
            }catch(ClassNotFoundException classNotFoundException){
                showMessage("\nUnknown object type");
            }
        }while(!message.equals("SERVER - END"));
    }

    //close the streams and sockets
    private void closeCrap(){
        showMessage("\nClosing down...");
        ableToType(false);
        try{
            output.close();
            input.close();
            connection.close();
        }catch(IOException ioException){
            ioException.printStackTrace();
        }
    }

    //send messages to server
    private void sendMessage(String message){
        try{
            output.writeObject("CLIENT - " + message);
            output.flush();
            showMessage("\nCLIENT - " + message);
        }catch(IOException ioException){
            chatWindow.append("\nMessage failed to send.");
        }
    }

    //change/update chatWindow
    private void showMessage(final String message){
        SwingUtilities.invokeLater(
            new Runnable(){
                public void run(){
                    chatWindow.append(message);

                }
            }
        );
    }

    //gives user permission to type text into the text box
    private void ableToType(final boolean tof){
        SwingUtilities.invokeLater(
            new Runnable(){
                public void run(){
                    userText.setEditable(tof);      
                }
            }
        );
    }

}

事前に、私が得ることができるあらゆる種類の応答に感謝し、感謝します:)

4

1 に答える 1

0

SO には少し広すぎますが、この種のサーバー/クライアント プログラムを処理する方法についての戦略を示します。詳細については、お気に入りの検索マシンをヒットしてください。たくさんの記事があるはずです。

複数のクライアント要求を処理するサーバーの基本戦略は次のとおりです。

while (true) {
    accept a connection;
    create a thread to deal with the client;
    start that thread;
}

このようにして、新しく作成された (そして開始された) スレッドが同時に実行されます。これにより、このサーバー コードを実行しているスレッドがループに戻りwhile (true)、「接続を受け入れる」行で停止し、次のクライアントを効果的に待機できるようになります。

したがって、基本的には次のようなものが必要です

while (true) {
    connection = server.accept();
    Thread clientHandler = new Thread(new ClientHandler(connection));
    clientHandler.start();
}

これには、すべてのクライアント通信を行うクラスのClientHandler実装が必要です。Runnable

プログラムにはリファクタリングが必要な部分がたくさんあることに注意してください。あなたのクラスChatServerはあまりにも多くの仕事をしています。さらに伸びていJFrameます。私の提案は同じリーグで行われ、最初の道に過ぎません。通常、受信するクライアント要求ごとに新しいスレッドを作成するのではなく、限られたスレッド プールを使用する必要があります。

于 2015-06-20T18:13:47.863 に答える