简体   繁体   English

Java:多线程聊天服务器仅向1个客户端发送消息

[英]Java: Multiple Thread Chat Server Sends message to only 1 client

After getting a lot of help in my previous questions finally I attempted to make a multiple client. 在我之前的问题中获得很多帮助之后,我终于尝试建立多个客户。 Its not working properly and I will try to explain the basics of code before posting whole code. 它无法正常工作,在发布整个代码之前,我将尝试解释代码的基本知识。

Basic Classes: 基本课程:

ChatServer.Java -- Starts a ServerSocket. ChatServer.Java-启动ServerSocket。 Waits for user to connect. 等待用户连接。 Adds user to ArrayList. 将用户添加到ArrayList。 Starts a new thread for every user. 为每个用户启动一个新线程。 The thread it starts will wait for inputs to come in from client and loop over list of clients and send the message to all. 它启动的线程将等待来自客户端的输入,并遍历客户端列表,并将消息发送给所有人。

CharServer2.Java : Just a GUI interface to start up Chat Server CharServer2.Java:仅一个GUI界面即可启动聊天服务器

Chat1: Connects to socket. 聊天1:连接到套接字。 send and receives messages. 发送和接收消息。 Both actions on different threads. 两种动作都在不同的线程上。

ChatClient.Java : GUI for Chat1 trigger. ChatClient.Java:Chat1触发器的GUI。

Now if I start the server and connect one client it works fine. 现在,如果我启动服务器并连接一个客户端,则可以正常工作。 If I add two clients things get rough :( . 如果我添加两个客户,事情会变得很糟:(。

Lets say I added User1 and User2. 可以说我添加了User1和User2。 User1 send message: ConcurrentModificationException User2 sends message : No exception. User1发送消息:ConcurrentModificationException User2发送消息:无异常。 The code loops at Arraylist. 该代码在Arraylist中循环。 Finds both sockets and tries to send message to both. 查找两个套接字,并尝试向两个套接字发送消息。 But the message reaches only User 1 但是邮件仅到达用户1

Another issue I have in code is that whenever I close window on any one of the users ChatServer throws exception that the socket was closed. 我在代码中遇到的另一个问题是,每当我关闭任何一个用户ChatServer上的窗口时,都会抛出套接字已关闭的异常。 Please note that all this is happening my local machine. 请注意,所有这一切都在我的本地计算机上发生。 Both users occupy different ports though. 但是,两个用户都占用不同的端口。

Here is the whole code: 这是完整的代码:

ChatServer.Java 聊天服务器

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;

public class ChatServer implements Runnable {

    private static int port; 
    private static String ip_add;
    private Socket socket;
    private ArrayList<Socket> clients;
    private ServerSocket ss;

    public ChatServer(String ip_add_in, int port_in) {
        // TODO Auto-generated constructor stub
        port = port_in;
        ip_add = ip_add_in;

        clients = new ArrayList<Socket>();
    }



    @Override
    public void run() {
        // TODO Auto-generated method stub

        System.out.println("ChatServer Start!!" + new Date() );

        try {
            ss = new ServerSocket(port, 10);

            while(true){
                socket = ss.accept();
                System.out.println("ChatServer Accepts!!" + new Date() );
                clients.add(socket);
                sendWelcomeMessage();

                Thread transmit = new Thread(new transmitMessagestoAll(socket));

                transmit.setName("" + socket.getPort());
                transmit.start();

//              (new Thread(new cleanUp(clients))).start();

                if(clients.isEmpty()) {
                    System.out.println("All users Gone");
                    break;
                }
            }


        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


    }

    public void sendWelcomeMessage() {
// send message via writer
    }


    public class transmitMessagestoAll implements Runnable {

        private ArrayList<Socket> clientList;
        private Socket currentClient;
        private BufferedReader reader;
        private PrintWriter writer;
        String msg;
        public transmitMessagestoAll(Socket curr){

            clientList = new ArrayList<Socket>();
            clientList = clients;
            currentClient = curr;
        }


        @Override
        public void run() {
            // TODO Auto-generated method stub


            System.out.println(Thread.currentThread().getName());


            while(!clientList.isEmpty()){


                System.out.println(clientList.size());
                try {
                    reader = new BufferedReader(new InputStreamReader(currentClient.getInputStream()));
                    msg = reader.readLine();


                    while(msg!=null){
                        for (Socket thisClient : clientList) {
                            System.out.println(Thread.currentThread().getName() 
                                               + ">>>>>"
                                               + thisClient.getPort());
                            writer = new PrintWriter(thisClient.getOutputStream());

                            System.out.println("Transmitting");
                            writer.println(msg);
                            writer.flush();
                            msg = reader.readLine();
                        }
                        System.out.println("-----------------");
                    }

                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    System.out.println("All users Gone! Breaking");
                    e.printStackTrace();
                    break;


                }

            }



        }


    }

Chat1.Java 聊天1.Java

import java.awt.*; 
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.*;

import javax.swing.*;
import javax.xml.ws.handler.MessageContext.Scope;


public class Chat1 {

    JFrame frame;
    JPanel msg_pan, chat_pan,connect_pan;
    JButton send,connect;
    JTextField server_ip;
    JTextArea type_area, chat_area;

    private static String user;
    private SendMsg send_action = new SendMsg();
    private Connect connect_action = new Connect();
    private Socket writerSocket; 
    //  private Socket readerSocket;
    static String ip_address;
    static int port;
    private PrintWriter writer;
    private ReaderThread readerRunner;
    private SenderThread senderRunner;
    Thread senderThread;


    Thread  readerThread;

    public Chat1(String name, String ip_add_in, int port_in){
        user = name;
        ip_address = ip_add_in;
        port = port_in;

    }


    public void create_window() {

    // GUI and add action Listeners 

    }



    class SendMsg implements ActionListener{

        @Override
        public void actionPerformed(ActionEvent e) {
            // TODO Auto-generated method stub
            String msg = type_area.getText();

            if (msg != null && msg != "") {
                msg = user + " :: "  +  msg ;
                senderRunner = new SenderThread(msg);
                type_area.setText(null);
                senderThread = new Thread(senderRunner);
                senderThread.start();
            }



        }


    }



    public void startchat(){



        create_window();

//      System.out.println("Window Done");

        connect_socket();



    }

    public void connect_socket(){

        try {
            System.out.println("Start Chat" + new Date());
            System.out.println(ip_address);
            System.out.println(port);
            writerSocket = new Socket(ip_address,port);

            if(writerSocket.isBound())
            {
                readerRunner = new ReaderThread();
                readerThread = new Thread(readerRunner);
                readerThread.start();

                System.out.println("Thread Started");

            }

        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


    }

    public class ReaderThread implements Runnable {

        InputStreamReader streamReader; 
        BufferedReader reader;
        String msg;

        public void run(){

            try {

                System.out.println("Entered ReaderThread Run");
                streamReader = new InputStreamReader(writerSocket.getInputStream());
                reader = new BufferedReader(streamReader);

                while (true) {
                    msg = reader.readLine();
                    if (msg != null) {
                        msg = msg + "\n";
                        chat_area.append(msg);  

                    }


                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            System.out.println("Leaving ReaderThread Run");

        }

    }

    public class SenderThread implements Runnable{

        String msg;
        public SenderThread(String msg_in){
            msg = msg_in + "\n";
        }

        public void run(){

            System.out.println("Entered SenderThread Run" + msg);


            try {

                if (writer == null) {
                    writer = new PrintWriter(writerSocket.getOutputStream());   
                }

                System.out.println("Writer has Error-->" + writer.checkError());

                writer.println(msg);
                writer.flush();
//              writer.close();

            } catch (UnknownHostException e) {
                // TODO Auto-generated catch block
                System.out.println("Sender Thread Run Exception 1");
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                System.out.println("Sender Thread Run Exception 2");
                e.printStackTrace();
            }

            System.out.println("Leaving SenderThread Run");

        }
    }

}

I found the bug in the code. 我在代码中找到了错误。 While the code was pushing out messages to all clients there was a readLine method call which effectively wiped out the text so it was pushing blank lines to second and other clients. 当代码向所有客户端推送消息时,有一个readLine方法调用有效地擦除了文本,因此将空白行推送至第二个客户端和其他客户端。 with that fix the issue with concurrentmodification also went away. 这样,并发修改的问题也消失了。 I can post the whole code for anyone who might be working on similar lines. 我可以将整个代码发布给可能正在从事类似工作的任何人。 Just add a comment and I will post it.. 只需添加评论,我将其发布..

Code Correction: Class ChatServer 代码更正:类ChatServer

  • Inner class : transmitMessagestoAll 内部类:sendMessagestoAll
  • Method Run, inside the loop on clientList the call to readLine was moved to outside the loop. 方法运行,在clientList的循环内,对readLine的调用移到了循环外。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM