qq多人群聊

这个Java程序实现了基于GUI的客户端和服务器端的简单聊天应用。客户端使用Swing创建登录和聊天界面,支持多线程读取服务器消息,并通过Socket进行网络通信。服务器端接收客户端连接,验证用户名并广播消息。程序涉及IO流、异常处理和集合等核心Java技术。
摘要由CSDN通过智能技术生成

Cilent

package demo.client;

import demo.common.Constant;

import javax.swing.;
import java.awt.
;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.net.Socket;

//多线程、IO、异常、集合、面向对象、网络编程
//gui
public class Client {
// 以下 是登录窗口的 属性
private JFrame loginFrame = null;
private JPanel loginJContentPane = null;
private JLabel loginlabShowMsg = null; //
private JLabel loginJlabName = null;
private JTextField loginTxtName = null;//
private JButton loginBtnLogin = null;//
// 以下 是主窗口的 属性
private JFrame mainFrame = null;
private JPanel mainJContentPane = null;
private TextArea mainShowTalk = null;
private JButton mainBtnSend = null;
private JLabel mainLabToSay = null;
private JTextField mainYouInput = null;

//io流
private BufferedOutputStream bos;
private BufferedInputStream bis;
private String colseId;

// 初始化 主窗口
private void initializeMainFrame() {
    mainFrame.setSize(406, 309);
    mainFrame.setResizable(false);
    if (mainJContentPane == null) {
        mainLabToSay = new JLabel();
        mainLabToSay.setBounds(new Rectangle(4, 243, 35, 27));
        mainLabToSay.setText("说吧:");
        mainJContentPane = new JPanel();
        mainJContentPane.setLayout(null);
        if (mainShowTalk == null) {
            mainShowTalk = new TextArea();
            mainShowTalk.setBounds(new Rectangle(4, 2, 395, 235));
            mainShowTalk
                    .setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
        }
        mainJContentPane.add(mainShowTalk, null);
        if (mainBtnSend == null) {
            mainBtnSend = new JButton();
            mainBtnSend.setBounds(new Rectangle(328, 243, 66, 24));
            mainBtnSend
                    .setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
            mainBtnSend.setFont(new Font("Dialog", Font.BOLD | Font.ITALIC,
                    14));
            mainBtnSend.setText("发送");
            mainBtnSend.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    //主窗口  点击发送按钮消息
                    send();
                }
            });
        }
        mainJContentPane.add(mainBtnSend, null);
        mainJContentPane.add(mainLabToSay, null);
        if (mainYouInput == null) {
            mainYouInput = new JTextField();
            mainYouInput.setText(null);
            mainYouInput.setBounds(new Rectangle(43, 242, 277, 28));
            mainYouInput.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    //主窗口  回车 发送按钮消息
                    send();
                }
            });
        }
        mainJContentPane.add(mainYouInput, null);
    }
    mainFrame.setContentPane(mainJContentPane);
    mainFrame.setTitle("聊天窗口");
    mainFrame.addWindowListener(new WindowAdapter() {
        public void windowClosing(WindowEvent e) {

// 关闭聊天室窗口
close();
}
});
}

//发送消息
private void send() {
    String input = mainYouInput.getText().trim();
    if(input.length()>0){
        //发送
        try {
            bos.write(input.getBytes());
            bos.flush();
            //清空输入框
            mainYouInput.setText("");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


// 初始化 登录窗口
private void initializeLoginFrame() {
    if (loginJContentPane == null) {
        loginlabShowMsg = new JLabel();
        loginlabShowMsg.setBounds(new Rectangle(102, 38, 138, 30));
        loginlabShowMsg.setFont(new Font("Dialog", Font.BOLD, 12));
        loginlabShowMsg.setForeground(Color.red);
        //loginlabShowMsg.setText("名字重复,隐姓埋名吧");
        loginlabShowMsg.setText(null);
        loginJlabName = new JLabel();
        loginJlabName.setBounds(new Rectangle(11, 3, 103, 30));
        loginJlabName.setFont(new Font("Dialog", Font.BOLD, 18));
        loginJlabName.setForeground(Color.blue);
        loginJlabName.setText("先报个名吧:");
        loginJContentPane = new JPanel();
        loginJContentPane.setLayout(null);
        loginJContentPane.add(loginJlabName, null);
        if (loginTxtName == null) {
            loginTxtName = new JTextField();
            loginTxtName.setBounds(new Rectangle(139, 2, 87, 33));
            loginTxtName.setFont(new Font("Dialog", Font.PLAIN, 18));
            loginTxtName.setText(null);
            // 向 loginTxtName 添加 动作事件
            loginTxtName.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    // 当 loginTxtName 被敲回车,执行登录操作
                    login();
                }
            });
        }

        if (loginBtnLogin == null) {
            loginBtnLogin = new JButton();
            loginBtnLogin.setBounds(new Rectangle(21, 37, 73, 31));
            loginBtnLogin.setFont(new Font("Dialog", Font.BOLD, 18));
            loginBtnLogin.setText("加入");
            // 向 loginBtnLogin 添加 动作事件
            loginBtnLogin.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    // 当 loginBtnLogin 被敲点击时,执行登录操作
                    login();
                }
            });
        }
        loginJContentPane.add(loginTxtName, null);
        loginJContentPane.add(loginBtnLogin, null);
        loginJContentPane.add(loginlabShowMsg, null);
    }
    loginFrame.setSize(261, 106);
    loginFrame.setResizable(false);
    loginFrame.setContentPane(loginJContentPane);
    loginFrame.setTitle("在线聊天室");
    // 添加窗口 关闭事件
    loginFrame.addWindowListener(new WindowAdapter() {
        // 如果 new 监听器(WindowListener) ,必须实现每一个方法
        // 如果 new 适配器(WindowListener) ,需要哪个就实现哪个
        public void windowClosing(WindowEvent e) {
            // 调用 close 方法关闭客户端
            close();
        }
    });
}
//关闭窗口
private void close() {
    try {
        bos.write(colseId.getBytes());
        bos.flush();
        System.exit(0);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

//登录方法
private void login() {
    //登录要干什么?
    //1。获取用户名
    String userName = loginTxtName.getText();
    try {
        //将用户名发送过去了
        bos.write(userName.getBytes());
        bos.flush();
        //获取反馈信息
        byte[] tong = new byte[1024];
        int len = bis.read(tong);
        String msg = new String(tong,0,len);
        if(Constant.SUCCESS_MSG.equals(msg)){
            loginSuccess();
        }else {
            loginFail();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

//登陆成功方法
private void loginSuccess() {
    mainFrame.setVisible(true);
    loginFrame.setVisible(false);
    loginTxtName.setText("");
    //登录成功,处于聊天界面,需要一直监听读,所以需要一个线程
    //因为显式消息需要用到mainShowTalk,所以要传到线程里
    new Thread(new ClientThread(bis,mainShowTalk)).start();
}

//登录失败方法
private void loginFail(){
    loginlabShowMsg.setText("名字重复,隐姓埋名吧");
}
//初始化ui
private void createUI() {
    loginFrame = new JFrame();
    this.initializeLoginFrame();
    loginFrame.setLocationRelativeTo(null);
    loginFrame.setVisible(true);
    mainFrame = new JFrame();
    this.initializeMainFrame();
    mainFrame.setLocationRelativeTo(null);
    mainFrame.setVisible(false);
}

// 客户端 启动方法
public void start() {
    // 1、画界面
    this.createUI();
    // 2 、连接服务器并初始化io
    this.connect();
    // 3 、初始化 IO
    //this.initIO();
    //4.获取closeId
    this.getCloseId();
}

private void getCloseId() {
    byte[] tong = new byte[1024];
    try {
        int len = bis.read(tong);
        colseId = new String(tong,0,len);
    } catch (IOException e) {
        e.printStackTrace();
    }

}


//客户端连接服务端
private void connect() {
    try {
        Socket socket = new Socket(Constant.IP, Constant.PORT);
        bos = new BufferedOutputStream(socket.getOutputStream());
        bis = new BufferedInputStream(socket.getInputStream());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

}package demo.client;

import java.awt.*;
import java.io.BufferedInputStream;
import java.io.IOException;

public class ClientThread implements Runnable {

private BufferedInputStream bis;
private TextArea mainShowTalk;

public ClientThread(BufferedInputStream bis, TextArea mainShowTalk) {
    this.bis = bis;
    this.mainShowTalk = mainShowTalk;
}

@Override
public void run() {
    byte[] tong = new byte[1024];
    int len;
    while (true){
        try {
            len = bis.read(tong);
            String msg = new String(tong,0,len);
            mainShowTalk.append(msg+"\n");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

}

Server

package demo.server;

import demo.common.Constant;

import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

public class Server {
//所有的客户端
private Map<String, Socket> clients = new HashMap<>();

public void start(){
    //启动一个服务段,然后,等待客户端连接
    try {
        ServerSocket serverSocket = new ServerSocket(Constant.PORT);
        System.out.println("服务端已启动,等待客户端连接");
        while (true){
            //服务端已启动,等待客户端连接
            Socket accept = serverSocket.accept();
            //启用一个线程,一直读客户端的数据
            new Thread(new ServerThread(accept,clients)).start();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

}
package demo.server;

import demo.common.Constant;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Map;
import java.util.UUID;

public class ServerThread implements Runnable {
private Socket socket;
private BufferedInputStream bis;
private BufferedOutputStream bos;
private Map<String, Socket> clients;
private Boolean flag = true;

public ServerThread(Socket socket,Map<String, Socket> clients) {
    this.socket = socket;
    this.clients = clients;
    //初始化流
    try {
        bis = new BufferedInputStream(socket.getInputStream());
        bos = new BufferedOutputStream(socket.getOutputStream());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

@Override
public void run() {
    //一直读客户端发送的数据,需要输入流
    int len;
    byte[] tong = new byte[1024];
    while (flag){
        try {
            //发送一个随机数给我们的客户端
            String closeId = UUID.randomUUID().toString();
            bos.write(closeId.getBytes());
            bos.flush();
            String userName;
            //读用户名
            while (true){
                len = bis.read(tong);
                userName = new String(tong, 0, len);
                //如果是closeId怎么办?
                if(userName.equals(closeId)){
                    this.close();
                }
                if(clients.get(userName)==null){
                    //这个名字不重复
                    clients.put(userName,this.socket);
                    //根据用户名反馈信息给客户端   id:ahabba   name:123
                    bos.write(Constant.SUCCESS_MSG.getBytes());
                    bos.flush();
                    //输出进入房间信息   欢迎张三进入聊天室
                    sendAll("欢迎"+userName+"进入聊天室");
                    break;
                }else{
                    //名字重复
                    bos.write(Constant.FAIL_MSG.getBytes());
                    bos.flush();
                }
            }
            //读消息
            while (true){
                len = bis.read(tong);
                String input = new String(tong,0,len);
                if(input.equals(closeId)){
                    clients.remove(userName);
                    sendAll(userName+"退出聊天室");
                    this.close();
                    break;
                }else{
                    sendAll(userName+": "+input);
                }
            }

        } catch (Exception e) {
        }
    }
}

private void close() {
    this.flag = false;
    try {
        socket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private void sendAll(String string) {
    BufferedOutputStream bos;
    for(Socket socket : clients.values()){
        try {
            bos = new BufferedOutputStream(socket.getOutputStream());
            bos.write(string.getBytes());
            bos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

}

Common

package demo.common;

public interface Constant {
String IP = “127.0.0.1”;
Integer PORT = 8888;

String SUCCESS_MSG = "成功123123";
String FAIL_MSG = "SHIB";

}

main

package demo.main;

import demo.client.Client;

public class StartClient {
public static void main(String[] args) {
new Client().start();
//实时打印同时在线用户(包括用户名和数量)
}
}

package demo.main;

import demo.server.Server;

public class StartServer {
public static void main(String[] args) {
new Server().start();
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值