java服务端对多个客户端的群聊功能代码实现

以下代码可以实现服务端发送一条消息,多个客户端可以同时收到这条消息,同时客户端可以单独的和服务端通信
需要注意的是,此时服务端只需要一个发送消息的进程

服务端代码:

/**
 * 实现多个客户端对应一个服务端进行通信
 * 
 * @author wangjue
 *
 */
public class MyServer {
    private ArrayList<Socket> list = new ArrayList<Socket>();
    public static void main(String[] args) {

        MyServer ms = new MyServer();
        ms.initServer(10010);
    }

    public void initServer(int port) {
        try {
            ServerSocket server = new ServerSocket(port);
            System.out.println("服务端正等待客户端连接...");
            /*
             *  启动发消息的线程
             *  因为是一个服务端对应多个客户端,因此发送消息的线程只需要一个,不需要随着客户端的个数增加而增加 
             */
            SendThread st = new SendThread(list);
            new Thread(st).start();

            // 表示可以连接多个客户端
            while (true) {
                Socket socket = server.accept();
                list.add(socket);
                System.out.println("已经有一个客户端连接上来了...");             
                //启动收消息的线程
                RecieveThread rt = new RecieveThread(socket);
                new Thread(rt).start();

            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
/**
 * 接收客户端不断传来消息的线程
 * 
 * @author wangjue
 *
 */
public class RecieveThread implements Runnable {
    private Socket socket;
    private String recieveMsg;
    public RecieveThread(Socket socket) {
        this.socket = socket;
    }
    public String getRecieveMsg() {
        return recieveMsg;
    }


    @Override
    public void run() {
        try {
            InputStream ips = socket.getInputStream();
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            while (true) {
                int t = ips.read();
                // 收到换行符为止
                while (t != '\n') {
                    bos.write(t);
                    t = ips.read();
                }
                byte[] b = bos.toByteArray();
                recieveMsg = new String(b);
                System.out.println(recieveMsg);
                bos.reset();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}
/**
 * 发送消息给多个客户端的线程
 * @author wangjue
 *
 */
public class SendThread implements Runnable {
    private ArrayList<Socket> list;
    public SendThread(ArrayList<Socket> list) {
        this.list = list;
    }
    @Override
    public void run() {
        try {
            while (true) {
                //wait for scanner input,scanner是阻塞性,若没有输出内容,代码会停止不往下执行
                Scanner sc = new Scanner(System.in);            
                String msg = "服务端说:" + sc.nextLine() + "----" + new Date(System.currentTimeMillis()) + "\n";
                //通过for循环依次取出所有已经连上的socket对象,将服务端发出的消息写到输入流
                for (int i = 0; i < list.size(); i++) {
                    OutputStream ops = list.get(i).getOutputStream();
                    ops.write(msg.getBytes());
                    ops.flush();
                }                           
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

客户端代码

public class MyClient {
    public static void main(String[] args) {
        MyClient mc = new MyClient();
        mc.initClient("127.0.0.1", 10010);

    }
    public void initClient(String host, int port) {
        try {
            Socket socket = new Socket(host, port);
            talkUI ui = new talkUI();
            ui.initUI();            
            // 启动收消息的线程
            RecieveThread rt = new RecieveThread(socket, ui);
            new Thread(rt).start();
            // 启动发消息的线程
            SendThread st = new SendThread(socket, ui);
            new Thread(st).start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
/**
 * 接收服务端传来的消息并显示在面板
 * @author wangjue
 *
 */

public class RecieveThread implements Runnable {
    private Socket socket;
    private talkUI ui;//传入面板对象,调用getArea1方法获取area1对象
    public RecieveThread(Socket socket,talkUI ui) {
        this.socket = socket;
        this.ui = ui;
    }

    @Override
    public void run() {
        try {
            InputStream ips = socket.getInputStream();
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            while (true) {
                int t = ips.read();
                while (t != '\n') {
                    bos.write(t);
                    t = ips.read();
                }
                byte[] b = bos.toByteArray();
                //收到服务端传来的消息
                String msg = new String(b);
                //将消息显示在消息面板上
                ui.getArea1().append(msg+"\n"); 
                //将服务端的消息接收到并显示在面板后,清空输入流,下次收到消息后就不会显示上次已经收到的消息
                bos.reset();

            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}
/**
 * 向服务端发送消息
 * @author wangjue
 *
 */
public class SendThread implements Runnable {
    private Socket socket;
    private talkUI ui; 
    public SendThread(Socket socket, talkUI ui) {
        this.socket = socket;
        this.ui = ui;
    }
    @Override
    public void run() {
        try {
            ui.ops = socket.getOutputStream();          
            while (true) {
                if(ui.sendMsg2!=null){
                    byte[] b = ui.sendMsg2.getBytes();
                    ui.ops.write(b);
                    ui.ops.flush();             
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
/**
 * 聊天面板
 * @author wangjue
 *
 */

public class talkUI implements ActionListener{
    private JTextArea area1 = new JTextArea(15,30);
    private JTextArea area2 = new JTextArea(10,30);
    public OutputStream ops;
    //在对话框输入的内容
    private String sendMsg;
    //传给服务端的内容
    public String sendMsg2;

    public JTextArea getArea1() {
        return area1;
    }
    public void initUI() {
         JFrame jf = new JFrame();
         jf.setTitle("私人聊天室");
         jf.setSize(400,600);
         FlowLayout layout = new FlowLayout();
         jf.setLayout(layout);
         //显示面板

         area1.setEditable(false);
         jf.add(area1);
         //输入面板

         jf.add(area2);
         //发送按钮
         JButton btn = new JButton("发送");
         jf.add(btn);
         jf.setDefaultCloseOperation(3);
         jf.setVisible(true);
         btn.addActionListener(this);
     }
    @Override
    public void actionPerformed(ActionEvent e) {
        sendMsg  = area2.getText();
        sendMsg2 = sendMsg+"\n"; //传给服务端的消息要加入换行符,服务端才能知道什么时候结束接收
        //输入的内容要显示在面板上
        area1.append("自己说:"+sendMsg+"----"+new Date(System.currentTimeMillis())+"\n");
        //点击发送后,输入面板要清空
        area2.setText("");
        //要每点击一次发送就要将内容写入输出流中
        try {
            ops.write(sendMsg2.getBytes());         
        } catch (IOException e1) {
            e1.printStackTrace();
        }       
    }
}

结果显示
这里写图片描述

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值