Java基于NIO实现群聊功能

本文实例为大家分享了Java基于NIO实现群聊功能的具体代码,供大家参考,具体内容如下

一、群聊服务器

package com.dashu.netty.group_chat;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;

public class GroupChatServer {

    /**
     * 初始化选择器
     */
    private Selector selector;

    /**
     * 初始化服务器网络通道
     */
    private ServerSocketChannel serverSocketChannel;

    /**
     * 端口
     */
    private static final int PORT = 6666;

    /**
     * 构造方法
     */
    public GroupChatServer() {

        try {

            //获取选择器
            selector = Selector.open();

            //获取服务器网络通道
            serverSocketChannel = ServerSocketChannel.open();

            //网络地址
            InetSocketAddress inetSocketAddress = new InetSocketAddress(PORT);

            //服务器网络通道绑定网络地址
            serverSocketChannel.socket().bind(inetSocketAddress);

            //设置服务器网络通道非阻塞
            serverSocketChannel.configureBlocking(false);

            //将服务器网络通道注册到选择器上,绑定连接请求事件
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

    /**
     * 监听客户端请求事件
     */
    public void listen() {

        try {

            //无限循环
            while (true) {

                //获取请求数
                int count = selector.select();

                //count大于0,则代表有请求进来
                if (count > 0) {

                    //获取请求集
                    Iterator<SelectionKey> selectionKeyIterator = selector.selectedKeys().iterator();

                    //遍历请求集
                    while (selectionKeyIterator.hasNext()) {

                        //得到请求
                        SelectionKey selectionKey = selectionKeyIterator.next();

                        //连接请求
                        if (selectionKey.isAcceptable()) {

                            //获取客户端网络通道
                            SocketChannel socketChannel = serverSocketChannel.accept();

                            //设置客户端网络通道非阻塞
                            socketChannel.configureBlocking(false);

                            //将客户端网络通道注册到选择器上
                            socketChannel.register(selector, SelectionKey.OP_READ);

                            System.out.println(socketChannel.getRemoteAddress() + "上线了");

                        }

                        //信息读取请求
                        if (selectionKey.isReadable()) {

                            //客户端信息读取
                            readData(selectionKey);

                        }

                        //移除请求
                        selectionKeyIterator.remove();

                    }

                } else {

                    System.out.println("等待...");

                }

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

    }

    /**
     * 客户端信息读取
     *
     * @param selectionKey
     */
    private void readData(SelectionKey selectionKey) {

        //初始化客户端网络通道
        SocketChannel socketChannel = null;

        try {

            //获取客户端网络通道
            socketChannel = (SocketChannel) selectionKey.channel();

            //创建缓冲区
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

            //读取客户端网络通道中的数据到缓冲区
            int count = socketChannel.read(byteBuffer);

            //判断缓冲区中是否有数据
            if (count > 0) {

                //将缓冲区的数据转换位字符串
                String message = new String(byteBuffer.array());

                System.out.println(message.trim());

                //将信息群发到其他客户端
                sendInfoToOtClients(message, socketChannel);

            }

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

    /**
     * 将信息群发到其他客户端
     *
     * @param message
     * @param socketChannel
     */
    private void sendInfoToOtClients(String message, SocketChannel socketChannel) {

        //获取所有注册到选择器的客户端,并遍历
        for (SelectionKey selectionKey : selector.keys()) {

            //获取通道
            Channel channel = selectionKey.channel();

            //判断通道是否属于SocketChannel,同时不等于发送信息的客户端
            if (channel instanceof SocketChannel && channel != socketChannel) {

                //通道转换
                SocketChannel sc = (SocketChannel) channel;

                //将信息写入缓冲区
                ByteBuffer byteBuffer = ByteBuffer.wrap(message.getBytes(StandardCharsets.UTF_8));

                try {

                    //将缓冲区的数据写入通道
                    sc.write(byteBuffer);

                } catch (Exception e) {

                    e.printStackTrace();

                }

            }

        }

    }

    public static void main(String[] args) {

        GroupChatServer groupChatServer = new GroupChatServer();

        System.out.println("服务器启动,开始监听客户端请求...");
        groupChatServer.listen();

    }

}

二、客户端

package com.dashu.netty.group_chat;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Scanner;

public class GroupChatClient {

    /**
     * 网络连接地址
     */
    private final String HOST = "127.0.0.1";

    /**
     * 端口
     */
    private final int PORT = 6666;

    /**
     * 初始化选择器
     */
    private Selector selector;

    /**
     * 初始化网络通道
     */
    private SocketChannel socketChannel;

    /**
     * 用户名
     */
    private String username;

    public GroupChatClient() {
        try {

            //获取选择器
            selector = Selector.open();

            //获取服务器网络地址
            InetSocketAddress inetSocketAddress = new InetSocketAddress(HOST, PORT);

            //获取网络通道
            socketChannel = SocketChannel.open(inetSocketAddress);

            //设置网络通道非阻塞
            socketChannel.configureBlocking(false);

            //将网络通道注册到选择器
            socketChannel.register(selector, SelectionKey.OP_READ);

            //获取用户名
            System.out.println("请输入用户名:");

            Scanner scanner = new Scanner(System.in);

            username = scanner.nextLine();

            System.out.println(username + " 进入群聊...");

        } catch (Exception e) {

            e.printStackTrace();

        }
    }

    /**
     * 向服务器发送信息
     *
     * @param message
     */
    public void sendInfo(String message) {

        message = username + ":" + message;

        try {

            //向通道写入数据
            socketChannel.write(ByteBuffer.wrap(message.getBytes(StandardCharsets.UTF_8)));

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

    /**
     * 读取服务器发来的信息
     */
    public void readInfo() {
        try {

            //获取请求数
            int count = selector.select();

            if (count > 0) {

                //获取请求集
                Iterator<SelectionKey> selectionKeyIterator = selector.selectedKeys().iterator();

                //遍历请求集
                while (selectionKeyIterator.hasNext()) {

                    //获取请求
                    SelectionKey selectionKey = selectionKeyIterator.next();

                    //判断位读请求
                    if (selectionKey.isReadable()) {

                        //获取通道
                        SocketChannel sc = (SocketChannel) selectionKey.channel();

                        //创建缓冲区
                        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

                        //读取通道的数据到缓冲区
                        sc.read(byteBuffer);

                        //缓冲区数据转字符串
                        String message = new String(byteBuffer.array());

                        //输出
                        System.out.println(message.trim());

                    }

                    //移除已完成请求
                    selectionKeyIterator.remove();

                }

            }

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

    public static void main(String[] args) {

        GroupChatClient groupChatClient = new GroupChatClient();

        /**
         * 开启一个线程,每3秒读取一次服务器发来的信息
         */
        new Thread() {
            @Override
            public void run() {
                while (true) {
                    groupChatClient.readInfo();
                    try {
                        Thread.sleep(3000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();

        //信息输入
        Scanner scanner = new Scanner(System.in);

        System.out.println("请输入信息:");
        while (scanner.hasNextLine()) {

            String s = scanner.nextLine();

            //信息发送
            groupChatClient.sendInfo(s);

            System.out.println("请输入信息:");

        }
    }

}

三、效果图

1、服务器

2、客户端01

3、客户端02

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

(0)

相关推荐

  • Java实现NIO聊天室的示例代码(群聊+私聊)

    功能介绍 功能:群聊+私发+上线提醒+下线提醒+查询在线用户 文件 Utils 需要用maven导入下面两个包 <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.18</version> </dependency> <dependency> <group

  • java实现小型局域网群聊功能(C/S模式)

    本文实例为大家分享了java群聊功能,供大家参考,具体内容如下 Java 对TCP协议的支持: --> java.net包中定义了两个类ServerSocket 和Socket ,分别用来实现双向连接的server 端和client 端.  --> Client 类定义客户端 package com.dragon.java.tcpchat; import java.io.IOException; import java.net.Socket; import java.net.UnknownHo

  • Java编程使用UDP建立群聊系统代码实例

    相关java类介绍 DatagramSocket public class DatagramSocket extends Object 此类表示用来发送和接收数据报包的套接字. 数据报套接字是包投递服务的发送或接收点.每个在数据报套接字上发送或接收的包都是单独编址和路由的.从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达. 在DatagramSocket上总是启用UDP广播发送.为了接收广播包,应该将DatagramSocket绑定到通配符地址,在某些实现中,将Dat

  • java Socket实现多人群聊与私聊功能

    本文实例为大家分享了java Socket实现多人群聊与私聊的具体代码,供大家参考,具体内容如下 关于Socket套接字的一些基本知识与认识可以参见上一篇或自行查阅. ServerSocket和Socket实现群聊与私聊涉及到多线程编程,实现过程的重点是利用Socket通信的原理,即不断的在服务端和客户端创建输入输出流来相互传递.交换数据等以达到通信的目的.具体实现如下: 服务端: import java.io.*; import java.net.*; import java.util.Has

  • Java基于NIO实现群聊功能

    本文实例为大家分享了Java基于NIO实现群聊功能的具体代码,供大家参考,具体内容如下 一.群聊服务器 package com.dashu.netty.group_chat; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.*; import java.nio.charset.StandardCharsets; import java.util.Iterator; pu

  • Java基于NIO实现群聊系统

    本文实例为大家分享了Java基于NIO实现群聊系统的具体代码,供大家参考,具体内容如下 实例要求: 1.编写一个 NIO 群聊系统,实现服务器端和客户端之间的数据简单通讯(非阻塞) 2.实现多人群聊 3.服务器端:可以监测用户上线,离线,并实现消息转发功能 4.客户端:通过 Channel 可以无阻塞发送消息给其它所有用户,同时可以接受其它用户发送的消息(有服务器转发得到) 5.目的:进一步理解 NIO 非阻塞网络编程机制 6.示意图分析和代码 // 服务端: package com.atgui

  • java基于NIO实现群聊模式

    本文实例为大家分享了java基于NIO实现群聊模式的具体代码,供大家参考,具体内容如下 Client package com.qst.chat; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.

  • Java基于NIO实现聊天室功能

    本文实例为大家分享了Java基于NIO实现聊天室功能的具体代码,供大家参考,具体内容如下 Sever端 package com.qst.one; import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.channels.Channel; import java.nio.channels.SelectableChannel; impor

  • java网络编程之群聊功能

    本文实例为大家分享了java网络编程之群聊功能的具体代码,供大家参考,具体内容如下 1.服务端 package networkCoding;   import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.Co

  • Java NIO实现群聊系统

    本文实例为大家分享了Java NIO实现群聊系统的具体代码,供大家参考,具体内容如下 前面的文章介绍了NIO的三大核心组件并编写了BIO的一个demo实例,本文使用NIO写一个小应用实例,巩固并加深对NIO的理解. 实例要求: 1)编写一个 NIO 群聊系统,实现服务器端和客户端之间的数据简单通讯(非阻塞) 2)实现多人群聊 3)服务器端:可以监测用户上线,离线,并实现消息转发功能 4)客户端:通过channel 可以无阻塞发送消息给其它所有用户,同时可以接受其它用户发送的消息(有服务器转发得到

  • Java使用MulticastSocket实现群聊应用程序

    本文实例为大家分享了Java使用MulticastSocket实现群聊应用程序的具体代码,供大家参考,具体内容如下 在这篇文章中,讨论了一个使用 MulticastSocket (Java Platform SE 7) 类的群聊应用程序.MulticastSocket 是一个 (UDP) DatagramSocket,具有加入 Internet 上其他多播主机“组”的附加功能. import java.net.*; import java.io.*; import java.util.*;  

  • Java基于堆结构实现优先队列功能示例

    本文实例讲述了Java基于堆结构实现优先队列功能.分享给大家供大家参考,具体如下: package Demo; import java.util.NoSuchElementException; /* * 小顶堆 java使用堆结构实现优先队列 */ public class JPriorityQueue<E> { @SuppressWarnings("hiding") class QueueNode<E> { int capacity; int size; E[

  • Java基于Tcp的基础聊天功能实例

    本文实例讲述了Java基于Tcp的基础聊天功能.分享给大家供大家参考,具体如下: 最基础的聊天,用户端和服务器端每次说一句,而且严格规定了先后到顺序. 服务器端: import java.io.*; import java.net.*; public class ChatServer { public static void main(String[] args) { ServerSocket server = null; try { server = new ServerSocket(1213

随机推荐