Java 多人聊天室

这篇具有很好参考价值的文章主要介绍了Java 多人聊天室。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Java实训做的多人聊天室,效果如图:

Java 多人聊天室

 功能:

  • 能够实现多个客户端之间的互相聊天,服务端来负责接收数据和转发数据。
  • 每个客户端可以自己设置和修改自己的名称,并传给服务器让其他客户端知道。
  • 当有客户端加入和退出时,群聊里每个客户端都有提示。(优化了异常检测,意外断开终止时也能不报错并提示用户xxx退出聊天室)
  • 当服务器异常断开或正常退出,客户端都可以提示并且程序不报错。
  • 服务端能够实时的显示在线的人数、  

关键技术: 

  • 集合(服务端并不是对一个客户端进行操作,是多个客户端之间来回通信充当转发数据的功能。服务端需要创建一个集合用来存放服务端连接对象。这样只要监听到客户端发送过来的数据,就可以遍历整个集合,转发给每一个客户端)
  • 多线程(客户端通过主线程来发送数据,还需要再启动一个线程来不断循环接收服务端转发过来的消息。服务端主线程使用while循环来不停的接收socket连接,然后为每个客户端的socket通道分配一个子线程接收)
  • 网络TCP传输的嵌套字socket(实现客户端和服务端之间的数据传输,选择TCP更安全可靠)
  • IO流(通道间的数据传输需要用到io流)

服务端代码:

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.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Iterator;

public class ServerChar extends JFrame {
    private static final int PORT = 8888;
    JTextArea jta = new JTextArea();
    JScrollPane jsp = new JScrollPane(jta);
    private JPanel south = new JPanel(); //面板
    private JLabel jb = new JLabel();
    private JButton stopBtn = new JButton("停止服务器");

    private boolean isStart = false;//服务器是否启动

    private ServerSocket serverSocket = null;

    private ArrayList<ClientConn> clientConn = new ArrayList<>();
    private int peopleOnline = 0;

    public ServerChar(){
        this.setTitle("服务端");
        this.add(jsp, BorderLayout.CENTER);
        jta.setEditable(false); //不能输入
        south.add(jb);
        jb.setText("聊天室在线人数: "+peopleOnline+"   ");
        south.add(stopBtn);
        this.add(south,BorderLayout.SOUTH);

        stopBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                isStart = false;
                    try {
                        if (serverSocket != null){
                            serverSocket.close();
                            isStart = false;
                        }
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }finally {
                        System.exit(0);
                    }
            }
        });

        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                isStart = false;
                try {
                    if (serverSocket != null){
                        serverSocket.close();
                        isStart = false;
                    }
                } catch (IOException ex) {
                    ex.printStackTrace();
                }finally {
                    System.exit(0);
                }
            }
        });
        this.setBounds(200,100,500,500);
        this.setVisible(true);
        startServer();
    }

    //服务器启动的方法
    public void startServer()  {
        try{
            try {
                serverSocket = new ServerSocket(PORT);
                isStart = true;
                jta.append("服务器已启动,等待客户端连接..."+System.lineSeparator());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            while(isStart){
                Socket socket = serverSocket.accept();
                clientConn.add(new ClientConn(socket));
                jta.append("客户端"+"["+socket.getInetAddress()+"-"+socket.getPort()+"]"+"加入聊天室"+System.lineSeparator());
                jb.setText("聊天室在线人数: "+(++peopleOnline)+"   ");
            }
        }catch (SocketException e){
            System.out.println("服务器中断");
        }catch (IOException e){
            e.printStackTrace();
        }
    }

    //这个对象属于服务器端的连接对象
    class ClientConn implements Runnable{
        Socket socket = null;
        //构造器 传入socket
        public ClientConn(Socket socket){
            this.socket=socket;
            (new Thread(this)).start();
        }

        @Override//同时接收客户端信息
        public void run() {
            String name = socket.getInetAddress()+"-"+socket.getPort();
            try {
            DataInputStream dis = new DataInputStream(socket.getInputStream());
            while (isStart){
                //读过来
                String str = dis.readUTF();
                if (str.startsWith("##")){
                    name = str.substring("##".length(),str.length());
                    jta.append("客户端"+"["+socket.getInetAddress()+"-"+socket.getPort()+"]"+"将名称设置为"+"["+name+"]"+System.lineSeparator());
                    Iterator<ClientConn> it = clientConn.iterator();
                    while(it.hasNext()) {
                        ClientConn o = it.next();
                        o.send(name+"加入了聊天室"+System.lineSeparator());
                    }
                }else{
                    jta.append("["+name+"]"+"说:"+str+System.lineSeparator());
                    //发过去
                    String strSend = "["+name+"]"+"说:"+str+System.lineSeparator();
                    //要遍历所有的客户端来发送 遍历ccList 调用send方法
                    Iterator<ClientConn> it = clientConn.iterator();
                    while(it.hasNext()) {
                        ClientConn o = it.next();
                        o.send(strSend);
                    }
                }
                }
            } catch (SocketException e){
                jta.append("客户端"+"["+name+"]"+"下线了"+System.lineSeparator());
                Iterator<ClientConn> it = clientConn.iterator();
                while(it.hasNext()) {
                    ClientConn o = it.next();
                    o.send(name+"退出了聊天室"+System.lineSeparator());
                }
                jb.setText("聊天室在线人数: "+(--peopleOnline)+"   ");
            } catch (IOException e) {
            e.printStackTrace();
            }
    }

        //对每个连接发送信息的方法
        public void send(String str){
            try {
                DataOutputStream dos = new DataOutputStream(this.socket.getOutputStream());
                dos.writeUTF(str);
                dos.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        new ServerChar();
    }

}

 客户端代码: 

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;

public class ClientChar extends JFrame implements KeyListener{
    public static void main(String[] args) throws IOException {
        new ClientChar().init();
    }
    //属性
    private boolean isConn = false;
    String name = "";

    private JTextArea jta;//文本域
    private JScrollPane jsp;//滚动条
    private JPanel jp;//面板
    private JTextField jtf;//文本框
    private JButton jb1;//发送信息
    //通道
    private Socket socket = null;
    private static final String CONNSTR = "127.0.0.1";
    private static final int CONNPORT = 8888;
    //流
    private DataOutputStream dos = null;

    //构造器
    public ClientChar(){
        //初始化组件
        jta = new JTextArea();
        jta.setEditable(false);//设置为不可编辑
        jsp = new JScrollPane(jta); //让文本域实现滚动效果
        //面板
        jp = new JPanel();
        jtf = new JTextField(15);
        jb1 = new JButton("发送信息");
    }

    public void init(){
        //将文本框和按钮添加到面板中
        jp.add(jtf);
        jtf.addKeyListener(this);
        jp.add(jb1);
        jb1.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //获取文本框内容
                String text = jtf.getText();
                sendMessage(text);
                if (text.length()==0){
                    return;
                }
                //拼接内容并发送
                jtf.setText("");
            }
        });

        //将滚动条与面板全部添加到窗口中
        this.add(jsp, BorderLayout.CENTER);
        this.add(jp, BorderLayout.SOUTH);

        //设置窗口
        this.setBounds(700, 300, 300, 300);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);

        try {
            socket = new Socket(CONNSTR,CONNPORT);
            isConn = true;
            name = JOptionPane.showInputDialog(this.getContentPane(), "请输入你的用户名:");
            dos = new DataOutputStream(socket.getOutputStream());
            dos.writeUTF("##"+name);
            dos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }

        this.setTitle("聊天室-"+name);
        //启动线程类接收
        new Thread(new Receive()).start();

    }

    //发送信息到服务器的方法
    private void sendMessage(String str) {
        try {
            if(jtf.getText().length()==0){
                return;
            }
            dos = new DataOutputStream(socket.getOutputStream());
            dos.writeUTF(str);
            dos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    @Override
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode()==KeyEvent.VK_ENTER){
            //回去输入框的内容
            String text = jtf.getText();
            //调用发送信息的方法
            sendMessage(text);
            //发送完后让输入框为空
            jtf.setText("");
        }
    }

    //多线程的类,实现了Runnable接口 用来接收
    class Receive implements Runnable{
        @Override
        public void run() {
            try {
                while (isConn) {
                    DataInputStream dis = new DataInputStream(socket.getInputStream());
                    String str = dis.readUTF(); //从管道读出服务端转发的数据 放到文本框里面
                    jta.append(str);
                    }
                } catch (SocketException e) {
                    System.out.println("服务器终止");
                    jta.append("服务器终止"+System.lineSeparator());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    @Override
    public void keyReleased(KeyEvent e) {

    }

    @Override
    public void keyTyped(KeyEvent e) {

    }
}

如果有帮助的话麻烦点赞收藏,谢谢。你的支持是对我最大的鼓励。文章来源地址https://www.toymoban.com/news/detail-498743.html

到了这里,关于Java 多人聊天室的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Python多人聊天室-基于socket UDP协议

    Python多人聊天室-基于socket UDP协议

    使用Python编写的基于socket UDP通信的多功能即时聊天室,包含Tkinter编写的图形化聊天界面,功能包括有账号注册和登录,登录成功后可以查看在线用户,并和聊天室内的其他在线用户聊天,包含私聊和群发,能发送文字、表情包,以及文件等。 登录和注册 显示在线用户 群聊

    2024年02月11日
    浏览(8)
  • C语言实现--基于UDP的多人在线聊天室

    C语言实现--基于UDP的多人在线聊天室

    目录 实现功能 实现思想 实现代码(部分及详解) 服务端部分代码 客户端部分代码 实现效果 项目中出现的问题和解决方法 项目整体代码展示 代码优化思路 服务端代码 客户端代码 服务端可以同时连接多个客户端; 新的客户端连接服务端时,可以在服务端显示自己的名字并

    2024年02月04日
    浏览(13)
  • 【Linux网络编程】基于UDP实现多人聊天室

    【Linux网络编程】基于UDP实现多人聊天室

    UDP(User Datagram Protocol)用户数据报协议,是不可靠的无连接的协议。在数据发送前,因为不需要进行连接,所以可以进行高效率的数据传输。 数据报格式套接字 SOCK_DGRAM 采用UDP只管发送数据而不去验证发送数据的正确性,不论传输是否被接收,数据流是否有丢失,都不再重新发

    2024年02月08日
    浏览(13)
  • 基于Python guI的多人聊天室的设计与实现

    基于Python guI的多人聊天室的设计与实现

    现在,即时聊天系统已成为 Internet 上的主要交流工具,并且涌现出大量的AP和平台。这些AP和平台都拥有更加完善的交换机制,使得人们可以更加便捷地进行沟通和交换信息。 广域网的聊天系统多重多样,知名的软件主要有 Facebook、腾讯 QQ 等。局域网聊天通信软件也有很多,

    2024年02月05日
    浏览(11)
  • 多人聊天室(带私聊功能)Linux网络编程基础

    多人聊天室(带私聊功能)Linux网络编程基础

    在和同学一起努力下终于完成了期末作业哈哈哈哈 文章目录 目录 前言 一、需求分析 二、功能设计 1.服务器端: 2.客户端: 三、流程图: 编程流程图: 服务器流程图: 客户端流程图: 四、运行效果: 项目源码: 服务器源码 客户端源码: 总结: Linux网络编程是我们这学

    2024年02月09日
    浏览(12)
  • Linux-Socket实现模拟群聊(多人聊天室)

    Linux-Socket实现模拟群聊(多人聊天室)

    简单版本 服务端源码 客户端源码 服务器可以在特定的端口监听客户端的连接请求,若连接成功,服务器采用广播的形式向当前所有连接客户端发送该客户端登录成功消息多个客户端可以同时登录,在源码文件中可以配置最多群聊同时在线人数。服务端接收到客户端发送的群

    2024年02月10日
    浏览(12)
  • WebSocket+Vue实现简易多人聊天室 以及 对异步调用的理解

    WebSocket+Vue实现简易多人聊天室 以及 对异步调用的理解

    代码仓库:github   HTTP是不支持长连接的,WebSocket是一种通信协议,提供了在单一、长连接上进行全双工通信的方式。它被设计用于在Web浏览器和Web服务器之间实现,但也可以用于任何需要实时通信的应用程序。使用ws作为协议标识符,如果需要加密则使用wss作为协议标识符

    2024年01月17日
    浏览(13)
  • 【Unity工具,简单应用】Photon + PUN 2,做一个简单多人在线聊天室

    【Unity工具,简单应用】Photon + PUN 2,做一个简单多人在线聊天室

    【Unity工具,简单学习】PUN 2,多人在线游戏开发,初步使用 需要有一定 UNITY 使用经验的开发者可以顺利阅读。 简单搭建一下大厅UI。 给 Laucher 节点一个 Launcher 脚本 Launcher 脚本如下,具体功能看注释 需要注意的是 PhotonNetwork.JoinOrCreateRoom(RoomName, new RoomOptions() { MaxPlayers = ma

    2024年02月08日
    浏览(31)
  • QT程序设计多人聊天室(基于QT、sqlite3、TCP/IP)

    QT程序设计多人聊天室(基于QT、sqlite3、TCP/IP)

    目录 技术路线 效果展示 程序主体 sqoperator.h mylogin.h myenroll.h chatinterface.h tips.h myapp.h ******************* sqoperator.cpp mylogin.cpp myenroll.cpp chatinterface.cpp tips.cpp myapp.cpp main.cpp widget.h widget.cpp main.cpp QT程序设计、sqlite数据库调用、TCP/IP客户端与服务端的搭建 通过次程序代码,可以学习如

    2024年02月09日
    浏览(15)
  • 使用Linux系统IO多路复用中eopll创建基于TCP通信协议的多人聊天室

    一.1.搭建好TCP的通信模型 2.创建红黑树根节点 3.将套接字事件添加到红黑树中,使其被监听 4.当套接字事件发生,表示有客户端连接,将连接事件加入到红黑树节点当中 5.每当连接事件发生时,表示客户端发送信息到服务器 6.每当有事件准备就绪时,将对应的红黑树节点信息

    2024年02月13日
    浏览(6)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包