广告
返回顶部
首页 > 资讯 > 后端开发 > Python >JavaBIO实现聊天程序
  • 935
分享到

JavaBIO实现聊天程序

2024-04-02 19:04:59 935人浏览 独家记忆

Python 官方文档:入门教程 => 点击学习

摘要

本文实例为大家分享了Java Bio实现聊天程序的具体代码,供大家参考,具体内容如下 我们使用一个聊天程序来说本文的主题 1、BIO 客户端服务器通讯 public class

本文实例为大家分享了Java Bio实现聊天程序的具体代码,供大家参考,具体内容如下

我们使用一个聊天程序来说本文的主题

1、BIO 客户端服务器通讯


public class ChatServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9000);
        while (true) {
            try {
                System.out.println("聊天服务已启动,等待客户连接....");
                Socket socket = serverSocket.accept();
                System.out.printf("建立了与%s的连接!\n",socket.getRemoteSocketAddress());
                loopReadRequest(socket);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static String loopReadRequest(Socket socket) throws IOException {
        InputStreamReader reader = new InputStreamReader(socket.getInputStream());
        StringBuilder sb = new StringBuilder();
        char[] cbuf = new char[256];
        
        // 循环读取socket的输入数据流
        while (true) {
            // read方法,读出内容写入 char 数组,read 方法会一直阻塞
            // 直到有输入内容 或 发生I/O错误 或 输入流结束(对方关闭了socket)
            // 正常读取时方法会返回读取的字符数,当输入流结束时(对方关闭了socket)方法返回 -1
            int readed = reader.read(cbuf);
   SocketAddress remoteSocketAddress = socket.getRemoteSocketAddress();
   // 客户端执行了socket.close()
            if (readed == -1) {
                System.out.println(remoteSocketAddress + " 断开了连接!");
                reader.close();
                socket.close();
                break;
            }

            String readedStr = new String(cbuf, 0, readed);
            sb.append(readedStr);

      // ready()用来判断流是否可被读取,如果reader缓冲区不是空则返回true,否则返回false
            if (!reader.ready()) {//reader缓冲区为空,表示数据流已读完
                // 数据流已读完,此时向客户端发送响应
                socket.getOutputStream().write((remoteSocketAddress+"你好,"+sb+"已收到").getBytes());
                System.out.println("收到内容:"+sb);
                // 清除sb的内容,准备接收下一个请求内容
                sb.setLength(0);
                System.out.println("等待客户端消息....");
            }
        }
        return sb.toString();
    }
}

public class ChatClient {
    public static void main(String[] args) {
        try {
            Socket socket = new Socket("localhost", 9000);
            Scanner scanner = new Scanner(System.in);
            while (true) {
                System.out.print(">");
                String line = scanner.nextLine();
                if("".equals(line)){
                    continue;
                }
                if ("quit".equals(line)) {
                    scanner.close();
                    socket.close();
                    break;
                }
                socket.getOutputStream().write(line.getBytes());
                System.out.println(readRequest(socket));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static String readRequest(Socket socket) throws IOException {
        InputStreamReader reader = new InputStreamReader(socket.getInputStream());
        StringBuilder sb = new StringBuilder();
        char[] cbuf = new char[256];
        while (true) {
            int readed = reader.read(cbuf);
            // 读出内容写入 char 数组,read 方法会一直阻塞
            // 直到有输入内容 或 发生I/O错误 或 输入流结束(对方关闭了socket)
            // 正常读取,方法会返回读取的字符数,而当输入流结束(对方关闭了socket)则返回 -1
            if (readed == -1) {
                System.out.println(socket.getRemoteSocketAddress() + " 断开了连接!");
                reader.close();
                socket.close();
                break;
            }

            String readedStr = new String(cbuf, 0, readed);
            sb.append(readedStr);
            if(!reader.ready()){
                break;
            }
        }
        return sb.toString();
    }
}

ChatServer与ChatClient建立了长连接,且ChatServer阻塞等待ChatClient发送消息过来,程序中 Server端只能与一个Client建立连接。程序这么写,只能实现一个客户端和服务端进行通信。

如何支持多个Client的连接呢? 使用独立的线程去读取socket

2、多线程实现单聊,群聊

单聊发送 格式:-c 对方端口号 消息内容, 群聊直接发送信息就可以了,具体发送逻辑看下面的程序


public class ChatServer {
    private static Map<String, Socket> connnectedSockets = new ConcurrentHashMap<>();

    public static void main(String[] args) throws IOException {

        // 1、服务端初始化工作
        ServerSocket serverSocket = new ServerSocket(9000);
        ExecutorService executorService = getExecutorService();

        // 2、主线程- 循环阻塞接收新的连接请求
        while (true) {
            Socket socket = serverSocket.accept();
            cacheSocket(socket);

            // 3、一个socket对应一个读取任务,交给线程池中的线程执行
            // 如果使用fixed线程池,会操作读取任务分配不到线程的情况
            // 现象就是发送的消息别人收不到(暂存在Socket缓存中)
            executorService.submit(createLoopReadTask(socket));
        }
    }

    private static Runnable createLoopReadTask(Socket socket) {
        return new Runnable() {
            public void run() {
                try {
                    loopReadRequestAndRedirect(socket);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        };
    }

    private static ExecutorService getExecutorService() {
        ExecutorService executorService = Executors.newCachedThreadPool();
        int nThreads = Runtime.getRuntime().availableProcessors();
        nThreads = 1;
        // 如果只设置一个线程,那么最先连接进来的客户端可以发送消息
        // 因为程序阻塞读取第一个socket连接的数据流,没有其他线程资源去读后面建立的socket了
        executorService = Executors.newFixedThreadPool(nThreads);
        return executorService;
    }

    private static void cacheSocket(Socket socket) {
        SocketAddress remoteSocketAddress = socket.getRemoteSocketAddress();
        String[] split = remoteSocketAddress.toString().split(":");
        connnectedSockets.put(split[1], socket);
    }

    public static String loopReadRequestAndRedirect(Socket socket) throws IOException {
        InputStreamReader reader = new InputStreamReader(socket.getInputStream());
        StringBuilder sb = new StringBuilder();
        char[] cbuf = new char[256];
        while (true) {
            SocketAddress remoteSocketAddress = socket.getRemoteSocketAddress();
            System.out.println(Thread.currentThread() + "执行 " + remoteSocketAddress + "发送的消息");
            // 读出内容写入 char 数组,read 方法会一直阻塞
            // 直到有输入内容 或 发生I/O错误 或 输入流结束(对方关闭了socket)
            // 正常读取时方法会返回读取的字符数,当输入流结束(对方关闭了socket)时返回 -1
            int readed = reader.read(cbuf);

            if (readed == -1) {
                System.out.println(remoteSocketAddress + " 断开了连接!");
                reader.close();
                socket.close();
                break;
            }

            String readedStr = new String(cbuf, 0, readed);
            sb.append(readedStr);

            //ready()用来判断流是否可被读取,如果reader缓冲区不是空则返回true,否则返回false
            boolean oneReqeustStreamReaded = !reader.ready();
            if (oneReqeustStreamReaded) {
                String requestContent = sb.toString().trim();
                String prifix = requestContent.substring(0, 2);
                // 单聊
                if ("-c".equals(prifix)) {
                    requestContent = requestContent.substring(3);
                    String port = requestContent.substring(0, requestContent.indexOf(" "));
                    requestContent = requestContent.replaceFirst(port, "");
                    sendToOneSocket(connnectedSockets.get(port), requestContent);
                    // 群聊
                } else {
                    // 向客户端发送响应
                    socket.getOutputStream().write(("您发送的消息-'" + sb + "' 已收到").getBytes());
                    sendToAllSocket(sb.toString(), socket);
                }
                sb.setLength(0);
            }
        }
        return sb.toString();
    }

    
    private static void sendToOneSocket(Socket socket, String msg) {
        // 对于同一个socket,同一时刻只有一个线程使用它发送消息
        synchronized (socket) {
            try {
                socket.getOutputStream().write(msg.getBytes("UTF-8"));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    
    private static void sendToAllSocket(String msg, Socket selfSocket) {
        for (String key : connnectedSockets.keySet()) {
            Socket socket = connnectedSockets.get(key);
            if (socket.equals(selfSocket)) {
                continue;
            }
            sendToOneSocket(socket, msg);
        }
    }
}


public class ChatClient {
    public static void main(String[] args) throws IOException {
        new ChatClient().start();
    }

    public void start() throws IOException {
        Socket socket = new Socket("localhost", 9000);
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        
        Runnable readTask = new Runnable() {
            public void run() {
                try {
                    loopReadRequest(socket);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        };
        executorService.submit(readTask);

        Runnable sendMsgTask = new Runnable() {
            public void run() {
                try {
                    Scanner scanner = new Scanner(System.in);
                    while (true) {
                        System.out.print(">");
                        String line = scanner.nextLine();
                        if ("".equals(line)) {
                            continue;
                        }
                        if ("quit".equals(line)) {
                            scanner.close();
                            socket.close();
                            break;
                        }
                        socket.getOutputStream().write(line.getBytes());
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        };
        executorService.submit(sendMsgTask);

    }

    public void loopReadRequest(Socket socket) throws IOException {
        InputStreamReader reader = new InputStreamReader(socket.getInputStream());
        StringBuilder sb = new StringBuilder();
        char[] cbuf = new char[256];
        while (true) {
            int readed = reader.read(cbuf);
            // 读出内容写入 char 数组,read 方法会一直阻塞
            // 直到有输入内容 或 发生I/O错误 或 输入流结束(对方关闭了socket)
            // 正常读取,方法会返回读取的字符数,而当输入流结束(对方关闭了socket)则返回 -1
            if (readed == -1) {
                System.out.println(socket.getRemoteSocketAddress() + " 断开了连接!");
                reader.close();
                socket.close();
                break;
            }

            String readedStr = new String(cbuf, 0, readed);
            sb.append(readedStr);
            if (!reader.ready()) {
                System.out.println(sb);
                sb.setLength(0);
            }
        }
    }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。

--结束END--

本文标题: JavaBIO实现聊天程序

本文链接: https://www.lsjlt.com/news/158213.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • JavaBIO实现聊天程序
    本文实例为大家分享了Java BIO实现聊天程序的具体代码,供大家参考,具体内容如下 我们使用一个聊天程序来说本文的主题 1、BIO 客户端服务器通讯 public class ...
    99+
    2022-11-12
  • C++实现聊天程序
    本文实例为大家分享了C++实现聊天程序的具体代码,供大家参考,具体内容如下 服务端 #include<iostream> #include<WinSock2.h...
    99+
    2022-11-12
  • 用Java实现聊天程序
    利用Java编写聊天程序,供大家参考,具体内容如下 首先计算机网络有两种传输层协议:TCP(面向连接),UDP(面向无连接)。今天就介绍基于这两种协议的聊天程序。 先查明自己电脑的主...
    99+
    2022-11-13
  • C++实现聊天小程序
    C++写一个游戏聊天服务器,供大家参考,具体内容如下 最近学习网络编程写了个聊天小程序,写个博客记录下自己的代码 涉及的技术: c++网络编程 c++多线程 ...
    99+
    2022-11-12
  • C++怎么实现聊天程序
    这篇文章主要为大家展示了“C++怎么实现聊天程序”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“C++怎么实现聊天程序”这篇文章吧。具体内容如下服务端#include<iostream>...
    99+
    2023-06-20
  • C++如何实现聊天小程序
    今天小编给大家分享一下C++如何实现聊天小程序的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。涉及的技术:c++网络编程c++...
    99+
    2023-06-08
  • 如何实现linux聊天室程序
    这篇文章主要讲解了“如何实现linux聊天室程序”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何实现linux聊天室程序”吧!代码一:#ifndef&nb...
    99+
    2022-10-19
  • java控制台实现聊天程序
    本文实例为大家分享了java控制台实现聊天程序的具体代码,供大家参考,具体内容如下 发送端 package ip.chat; import java.io.BufferedRe...
    99+
    2022-11-12
  • java NIO实现简单聊天程序
    本文实例为大家分享了java NIO实现简单聊天程序的具体代码,供大家参考,具体内容如下 服务端 功能: 1、接受客户端连接 2、发送消息 3、读取客户端消息 Server.jav...
    99+
    2022-11-12
  • java实现实时通信聊天程序
    利用TCP传输数据,编写客户端和服务器的程序,实现两个程序间的实时通信。 在每个程序中实现了实时的发送与接收数据的功能。 客户端的io界面 服务器端的io界面 io演示 程序以...
    99+
    2022-11-13
  • Python 聊天程序
    一、套接字 套接字是为特定网络协议(例如TCP/IP,ICMP/IP,UDP/IP等)套件对上的网络应用程序提供者提供当前可移植标准的对象。它们允许程序接受并进行连接,如发送和接受数据。为了建立通信通道,网络通信的每个端点拥有一个套接字对...
    99+
    2023-01-31
    程序 Python
  • C++ SOCKET多线程实现聊天小程序
    本文实例为大家分享了C++ SOCKET多线程实现聊天小程序的具体代码,供大家参考,具体内容如下 TCP/IP协议与SOCKET 什么是网络协议? 计算机网络中,各个实体之间的数据交...
    99+
    2022-11-12
  • Java实现局域网聊天小程序
    本文实例为大家分享了Java实现局域网聊天的具体代码,供大家参考,具体内容如下 开发环境: IDEA 2018.2 集成开发工具。 实现功能: 1、用户上线,向服务器通知并注册。 2...
    99+
    2022-11-13
  • python实现简单的聊天小程序
    概要 这是一个使用python实现一个简单的聊天室的功能,里面包含群聊,私聊两种聊天方式.实现的方式是使用套接字编程的一个使用TCP协议 c/s结构的聊天室 实现思路 x01 服务端的建立 首先,在服务端,使用soc...
    99+
    2022-06-02
    python 聊天 小程序
  • 利用QT实现UDP聊天小程序
    利用QT的UDP技术,实现两个QT程序之间的聊天程序。 示例代码 #ifndef WIDGET_H #define WIDGET_H #include <QWidget&g...
    99+
    2022-11-21
    QT UDP聊天程序 QT UDP聊天 QT UDP
  • Java NIO怎么实现聊天室程序
    本文小编为大家详细介绍“Java NIO怎么实现聊天室程序”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java NIO怎么实现聊天室程序”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。服务端:package&n...
    99+
    2023-06-17
  • 怎么用C++实现聊天小程序
    本篇内容介绍了“怎么用C++实现聊天小程序”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!C++写一个游戏聊天服务器,供大家参考,具体内容如下...
    99+
    2023-06-20
  • 小程序实现实时聊天IM功能
    随着小程序的发展,给公司带来了不错的收益,但是有件比较苦恼的事情是,由于小程序没有即时聊天功能,这给公司的客服带来不少的麻烦,导致沟通没有时效性。通过更智能的企达第三方小程序IM,可以实现更多多维度的操作!主动邀请对话当用户进入小程序后,可...
    99+
    2023-06-05
  • 【uni-app】小程序实现微信在线聊天(私聊/群聊)
    之前学习使用uni-app简单实现一个在线聊天的功能,今天记录一下项目核心功能的实现过程。页面UI以及功能逻辑全部来源于微信,即时聊天业务的实现使用socket.io,前端使用uni-app开发,后端服务器基于node实现,数据库选择mon...
    99+
    2023-09-03
    uni-app 前端 小程序
  • Android中基于XMPP协议实现IM聊天程序与多人聊天室
    简单的IM聊天程序 由于项目需要做一个基于XMPP协议的Android通讯软件。故开始研究XMPP。 XMPP协议采用的是客户端-服务器架构,所有从一个客户端发到另一个客户端的...
    99+
    2022-06-06
    xmpp 程序 聊天室 Android
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作