用java编写一个网络聊天室

网络聊天室

服务器:

1.启动服务器,在服务器端循环监听客户端的连接

java 复制代码
try {
            ServerSocket serverSocket=new ServerSocket(6622);
            System.out.println("服务器已启动");
            while(true){//把客户端实例添加到sockets里
                Socket socket=serverSocket.accept();
                sockets.add(socket);
                System.out.println("当前连接到客户端数量:"+sockets.size());

                //为每一个链接过来的客户端开一个线程
                new SocketThread(socket).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("服务器创建失败");
        }

2.把循环接收到的多个客户端Socket对象存储起来(集合)

java 复制代码
ArrayList<Socket> sockets=new ArrayList<>();

3.在服务器端每个Socket都要监听各自客户端发来的消息

java 复制代码
while(true){
                try {
                    String msg=dataInputStream.readUTF();
                    jTextAreamsg.append(msg+"\n");//在服务器端显示msg
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    System.out.println("客户端下线了");
                }
            }

4.一旦某个客户端发送了消息,那么在服务器端,就将此消息转发给其他的客户

java 复制代码
//向不同客户端转发消息
                    //遍历sockets
                    for (Socket socket:sockets){//客户端1 客户端2 客户端3
                        DataOutputStream dataOutputStream=new DataOutputStream(socket.getOutputStream());
                        dataOutputStream.writeUTF(msg);
                    }
客户端:

1.用户登录,创建Socket

java 复制代码
 Socket socket = new Socket("xxxxxxxxx", 6622);

2.如果Socket创建成功,打开聊天窗口

java 复制代码
new ChatWindow(jTextaccount.getText(), socket);//打开聊天窗口

3.输入内容,点击发送按钮发送消息

4.在客户端监听服务器发送回来的消息,并把消息显示出来

java 复制代码
class ClientThread extends Thread{
        DataInputStream dataInputStream;
        public ClientThread(Socket socket) throws IOException {
            dataInputStream=new DataInputStream(socket.getInputStream());
        }

        @Override
        public void run() {
            while(true){
                try {
                    String msg=dataInputStream.readUTF();
                    jTextArea.append(msg+"\n");//可以显示聊天内容并且保持原先内容
                } catch (IOException e) {
                    e.printStackTrace();
                    break;
                }
            }
        }
    }

完整代码:

ChatWindow:

java 复制代码
public class ChatWindow extends JFrame {
    JTextArea jTextArea;
    public ChatWindow(String name, Socket socket) throws IOException {
        DataOutputStream dos=new DataOutputStream(socket.getOutputStream());
        this.setTitle("欢迎"+name+"登录");
        this.setSize(500,500);
        this.setLocationRelativeTo(null);//居中
        this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);//关闭窗口时退出程序
        this.setResizable(false);//禁止窗口拖拽

        //创建面板
        JPanel jPanel=new JPanel();
        jTextArea=new JTextArea(22,43);//显示文本域
        jTextArea.setEditable(false);//不可修改的
        JTextArea jTextArea2=new JTextArea(5,33);//发送文本域
        jTextArea2.setLineWrap(true);//强制换行
        JScrollPane j=new JScrollPane(jTextArea2);//滚动条
        JButton jButtonsend=new JButton("发送");

        jPanel.add(jTextArea);
        jPanel.add(j);
        jPanel.add(jButtonsend);


        this.add(jPanel);

        this.setVisible(true);

        //来到聊天窗口

        jButtonsend.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String message=jTextArea2.getText();
                if(message.length()==0){//输入为空
                    JOptionPane.showMessageDialog(null,"发送内容不能为空");
                    return;
                }
                else{
                    //不为空,向服务器发送消息
                    String msg=name+"  "+new SimpleDateFormat("HH:mm:ss").format(new Date());
                    msg=msg+"\n"+message;
                    try {
                        dos.writeUTF(msg);
                        //发送成功清空发送内容
                        jTextArea2.setText("");
                    } catch (IOException ioException) {
                        ioException.printStackTrace();
                        JOptionPane.showMessageDialog(null,"内容发送失败,请检查网络连接");
                    }
                }
            }
        });
        new ClientThread(socket).start();
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                int res=JOptionPane.showConfirmDialog(null,"你确定要退出聊天吗?","警告",JOptionPane.OK_CANCEL_OPTION);
                if(res==0){
                    //点击确定
                    new LoginWindow();
                    dispose();
                }
            }
        });
    }

    //监听服务器发的消息(即客户端123的消息)
    class ClientThread extends Thread{
        DataInputStream dataInputStream;
        public ClientThread(Socket socket) throws IOException {
            dataInputStream=new DataInputStream(socket.getInputStream());
        }

        @Override
        public void run() {
            while(true){
                try {
                    String msg=dataInputStream.readUTF();
                    jTextArea.append(msg+"\n");//可以显示聊天内容并且保持原先内容
                } catch (IOException e) {
                    e.printStackTrace();
                    break;
                }
            }
        }
    }

}

LoginWindow:

java 复制代码
public class LoginWindow extends JFrame {
    public LoginWindow(){
        this.setTitle("欢迎登录");
        this.setSize(500,350);
        this.setLocationRelativeTo(null);//居中
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭窗口时退出程序
        this.setResizable(false);//禁止窗口拖拽

        JPanel jPanel=new JPanel();
        JLabel jLabel=new JLabel("欢迎登录");
        jLabel.setFont(new Font("横体", Font.BOLD,30));
        jPanel.add(jLabel);//欢迎登录

        //中间第一个空标签
        JLabel jLabel1=new JLabel();//欢迎登录下面空白部分
        jLabel1.setPreferredSize(new Dimension(500,50));

        //账号
        JLabel jLabelAccount=new JLabel("账号");//账号标签
        jLabelAccount.setPreferredSize(new Dimension(30,30));
        JTextField jTextaccount=new JTextField(15);//账号文本域


        //中间第二个空标签
        JLabel jLabel2=new JLabel();//欢迎登录下面空白部分
        jLabel2.setPreferredSize(new Dimension(500,20));

        //密码
        JLabel jLabelPassword=new JLabel("密码 ");//账号标签
        jLabelPassword.setPreferredSize(new Dimension(30,30));
        JPasswordField jPasswordField=new JPasswordField(15);

        //中间第二个空标签
        JLabel jLabel3=new JLabel();//欢迎登录下面空白部分
        jLabel3.setPreferredSize(new Dimension(500,20));

        //按钮
        JButton ButtonLogin=new JButton("登录");
        JButton ButtonSign=new JButton("注册");

        jPanel.add(jLabel1);
        jPanel.add(jLabelAccount);
        jPanel.add(jTextaccount);
        jPanel.add(jLabel2);
        jPanel.add(jLabelPassword);
        jPanel.add(jPasswordField);
        jPanel.add(jLabel3);
        jPanel.add(ButtonLogin);
        jPanel.add(ButtonSign);
        this.add(jPanel);
        this.setVisible(true);

        //按钮事件
        ButtonLogin.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if(jTextaccount.getText().equals("")||jPasswordField.getText().equals("")){//当账号或密码为空时,弹出警告
                    JOptionPane.showMessageDialog(null,"账号和密码不能为空","警告",JOptionPane.ERROR_MESSAGE);
                    return;
                }
                else if(!((jTextaccount.getText().matches("\\w{1,100}"))&&(jPasswordField.getText().matches("\\w{1,100}")))){//当1-100范围内不是字母和数字时弹出警告
                    JOptionPane.showMessageDialog(null,"账号密码只能由数字,字母组成","警告",JOptionPane.ERROR_MESSAGE);
                    return;
                }
                //创建Socket
                else {
                    try {
                        Socket socket = new Socket("10.13.0.67", 6622);
                        new ChatWindow(jTextaccount.getText(), socket);//打开聊天窗口
                        dispose();//释放窗口
                    } catch (IOException ioException) {
                        ioException.printStackTrace();
                        JOptionPane.showMessageDialog(null, "服务器连接失败,请稍后再试");
                    }
                }
            }

        });
    }
}

Run:

public class Run {
    public static void main(String[] args) {
            new LoginWindow();
    }
}

Server:

java 复制代码
public class Server extends JFrame {

    JTextArea jTextAreamsg;//放到成员变量便于在内部类中也可以使用
    //客户端连接的数量
    ArrayList<Socket> sockets=new ArrayList<>();

    public void ServerStart(){
        this.setTitle("我是服务器");
        this.setSize(500,500);
        this.setLocationRelativeTo(null);//居中
        this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);//关闭窗口时退出程序
        this.setResizable(false);//禁止窗口拖拽

        JPanel jPanel=new JPanel();
        jTextAreamsg=new JTextArea(28,43);
        jTextAreamsg.setLineWrap(true);//强制换行
        JScrollPane jScrollPane=new JScrollPane();
        jTextAreamsg.setEditable(false);//不可修改的

        jPanel.add(jTextAreamsg);
        jPanel.add(jScrollPane);

        this.add(jPanel);
        this.setVisible(true);

        //关闭窗口
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                int res=JOptionPane.showConfirmDialog(null,"你确定要关闭服务器吗?","警告",JOptionPane.OK_CANCEL_OPTION);
                if(res==0){//点击确定
                    dispose();
                }
            }
        });

        try {
            ServerSocket serverSocket=new ServerSocket(6622);
            System.out.println("服务器已启动");
            while(true){//把客户端实例添加到sockets里
                Socket socket=serverSocket.accept();
                sockets.add(socket);
                System.out.println("当前连接到客户端数量:"+sockets.size());

                //为每一个链接过来的客户端开一个线程
                new SocketThread(socket).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("服务器创建失败");
        }
    }




    //内部类,用来监听自己客户端有没有发消息
    class SocketThread extends Thread{
        Socket socket;//用来引入到run方法
        DataInputStream dataInputStream;
        public SocketThread(Socket socket) throws IOException {
            this.socket=socket;//把成员变量socket赋值为传入的socket参数,以便于客户端下线后可以从sockets里移除客户端
            dataInputStream=new DataInputStream(socket.getInputStream());
        }

        @Override
        public void run() {
            //循环监听客户端自己发送消息
            while(true){
                try {
                    String msg=dataInputStream.readUTF();
                    jTextAreamsg.append(msg+"\n");//在服务器端显示msg
                    //向不同客户端转发消息
                    //遍历sockets
                    for (Socket socket:sockets){//客户端1 客户端2 客户端3
                        DataOutputStream dataOutputStream=new DataOutputStream(socket.getOutputStream());
                        dataOutputStream.writeUTF(msg);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    System.out.println("客户端下线了");
                    sockets.remove(socket);
                    break;
                }
            }
        }
    }
}

ServerRun:

java 复制代码
public class ServerRun {
    public static void main(String[] args) {
        new Server().ServerStart();
    }
}

在这个过程中监听服务器消息和监听客户端消息都用到了内部类,这样的好处是可以之间在内部类中使用大类里面的jTextArea和sockets

相关推荐
西柚与蓝莓1 小时前
【开源开放体系总结】
python
程序员南飞1 小时前
ps aux | grep smart_webrtc这条指令代表什么意思
java·linux·ubuntu·webrtc
弥琉撒到我1 小时前
微服务swagger解析部署使用全流程
java·微服务·架构·swagger
一颗花生米。2 小时前
深入理解JavaScript 的原型继承
java·开发语言·javascript·原型模式
问道飞鱼2 小时前
Java基础-单例模式的实现
java·开发语言·单例模式
belldeep4 小时前
python:reportlab 将多个图片合并成一个PDF文件
python·pdf·reportlab
小堃学编程5 小时前
计算机网络(十) —— IP协议详解,理解运营商和全球网络
网络·tcp/ip·计算机网络
ok!ko5 小时前
设计模式之原型模式(通俗易懂--代码辅助理解【Java版】)
java·设计模式·原型模式
2402_857589366 小时前
“衣依”服装销售平台:Spring Boot框架的设计与实现
java·spring boot·后端
吾爱星辰6 小时前
Kotlin 处理字符串和正则表达式(二十一)
java·开发语言·jvm·正则表达式·kotlin