Java:多线程聊天服务器仅向 1 个客户端发送消息 [英] Java: Multiple Thread Chat Server Sends message to only 1 client

查看:47
本文介绍了Java:多线程聊天服务器仅向 1 个客户端发送消息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我之前的问题中得到了很多帮助后,我终于尝试制作多个客户端.它无法正常工作,我将在发布整个代码之前尝试解释代码的基础知识.

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.

基础类:

ChatServer.Java -- 启动一个 ServerSocket.等待用户连接.将用户添加到 ArrayList.为每个用户启动一个新线程.它启动的线程将等待来自客户端的输入并循环遍历客户端列表并将消息发送给所有人.

ChatServer.Java -- Starts a ServerSocket. Waits for user to connect. Adds user to 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 : 只是一个启动聊天服务器的 GUI 界面

CharServer2.Java : Just a GUI interface to start up Chat Server

Chat1: 连接到套接字.发送和接收消息.这两个动作都在不同的线程上.

Chat1: Connects to socket. send and receives messages. Both actions on different threads.

ChatClient.Java : Chat1 触发器的 GUI.

ChatClient.Java : GUI for Chat1 trigger.

现在,如果我启动服务器并连接一个客户端,它就可以正常工作.如果我添加两个客户,事情就会变得很粗糙:(.

Now if I start the server and connect one client it works fine. If I add two clients things get rough :( .

假设我添加了 User1 和 User2.User1 发送消息:ConcurrentModificationExceptionUser2 发送消息:也不例外.代码在 Arraylist 处循环.找到两个套接字并尝试向两者发送消息.但消息只到达用户 1

Lets say I added User1 and User2. User1 send message: ConcurrentModificationException User2 sends message : No exception. The code loops at Arraylist. Finds both sockets and tries to send message to both. But the message reaches only User 1

我在代码中遇到的另一个问题是,每当我关闭任何一个用户 ChatServer 上的窗口时,都会抛出套接字已关闭的异常.请注意,这一切都发生在我的本地机器上.两个用户虽然占用不同的端口.

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. Please note that all this is happening my local machine. Both users occupy different ports though.

完整代码如下:

ChatServer.Java

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

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");

        }
    }

}

推荐答案

我发现了代码中的错误.当代码向所有客户端推送消息时,有一个 readLine 方法调用,它有效地清除了文本,因此它将空行推送到第二个和其他客户端.有了这个修复,并发修改的问题也消失了.我可以为可能从事类似工作的任何人发布整个代码.只需添加评论,我就会发布它..

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. 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..

代码更正:类 ChatServer

Code Correction: Class ChatServer

  • 内部类:transmitMessagestoAll
  • 方法运行,在 clientList 的循环内,对 readLine 的调用移到了循环外.

这篇关于Java:多线程聊天服务器仅向 1 个客户端发送消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆