繁体   English   中英

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

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

在我之前的问题中获得很多帮助之后,我终于尝试建立多个客户。 它无法正常工作,在发布整个代码之前,我将尝试解释代码的基本知识。

基本课程:

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

CharServer2.Java:仅一个GUI界面即可启动聊天服务器

聊天1:连接到套接字。 发送和接收消息。 两种动作都在不同的线程上。

ChatClient.Java:Chat1触发器的GUI。

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

可以说我添加了User1和User2。 User1发送消息:ConcurrentModificationException User2发送消息:无异常。 该代码在Arraylist中循环。 查找两个套接字,并尝试向两个套接字发送消息。 但是邮件仅到达用户1

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

这是完整的代码:

聊天服务器

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;


                }

            }



        }


    }

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

        }
    }

}

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

代码更正:类ChatServer

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

暂无
暂无

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

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