千家信息网

Java NIO怎么实现聊天室功能

发表于:2025-02-02 作者:千家信息网编辑
千家信息网最后更新 2025年02月02日,这篇文章主要介绍了Java NIO怎么实现聊天室功能,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。具体内容如下代码里面已经包含了必要的
千家信息网最后更新 2025年02月02日Java NIO怎么实现聊天室功能

这篇文章主要介绍了Java NIO怎么实现聊天室功能,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

具体内容如下

代码里面已经包含了必要的注释,这里不详述了。实现了基本的聊天室功能。

常量类:

public class Constant {    public static final int serverPort = 44444;}

服务端:

package server; import java.io.IOException;import java.net.InetSocketAddress;import java.net.SocketAddress;import java.nio.ByteBuffer;import java.nio.channels.ClosedChannelException;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;import java.nio.charset.Charset;import java.util.Iterator;import java.util.Set; import constant.Constant; public class SocketServer {    private Charset charset = Charset.forName("UTF-8");    private ServerSocketChannel serverSocketChannel;    private Selector serverSocketSelector;    private SelectionKey serverRegisterKey;    private ByteBuffer buffer = ByteBuffer.allocate(1024);     public static void main(String[] args) throws IOException {        new SocketServer().openServer(new InetSocketAddress(Constant.serverPort));    }     public void openServer(SocketAddress address) throws IOException {        init(address);        handle();    }     private void init(SocketAddress address) throws IOException {        serverSocketSelector = Selector.open();         serverSocketChannel = ServerSocketChannel.open();        serverSocketChannel.configureBlocking(false);        serverRegisterKey = serverSocketChannel.register(serverSocketSelector, SelectionKey.OP_ACCEPT);         serverSocketChannel.socket().bind(address);    }     private void handle() throws IOException {        System.out.println("服务端open");        while (serverSocketSelector.select() > 0) {            Iterator iterator = serverSocketSelector.selectedKeys().iterator();             // 为什么这里要用迭代器,而不用增强for循环之类的呢?是因为这里获得一个key之后,要对其进行移除,避免二次处理,造成影响            while (iterator.hasNext()) {                dispatch(iterator.next());                iterator.remove();            }        }    }     private void dispatch(SelectionKey key) throws IOException {        if (key.isAcceptable()) {            accept(key);        } else if (key.isReadable()) {            readMessage(key);        } else if (key.isValid() && key.isWritable()) {            writeMessage(key);        }    }     private void accept(SelectionKey key) throws IOException, ClosedChannelException {        // 主要的是,接收事件是发生在服务器这边的,所以这边的通道要强转为ServerSocketChannel        ServerSocketChannel server = (ServerSocketChannel) key.channel();        SocketChannel client = server.accept();        client.configureBlocking(false);        // 同时再给该通道注册选择器,监听的内容的读取        client.register(serverSocketSelector, SelectionKey.OP_READ);    }     private void readMessage(SelectionKey key) throws IOException {        SocketChannel client = (SocketChannel) key.channel();        client.read(buffer);        // 调整为读取模式        buffer.flip();        String content = charset.decode(buffer).toString();        // 压缩空间,即抛弃已经读取的内容(实际上还在里面,只是处于等待被覆盖状态)        buffer.compact();        // 这里可以根据业务逻辑,设置不设置都可以,但是这里想接受到消息后立马回复一条消息,所以设置下一次感兴趣的(监听)事件为写        key.interestOps(SelectionKey.OP_WRITE);        // 设置系统回复信息        key.attach("系统已经收到你的消息\n");        // 开始广播这个客户端的内容到其他客户端        broadcast(key, content);    }     private void broadcast(SelectionKey self, String content) throws IOException {        Set selectedKeys = self.selector().keys();        for (SelectionKey key : selectedKeys) {             // 不能发送给自己,也不要服务器自己本身对这个有反应            if (key != self && key != serverRegisterKey) {                String oldMessage = (String) key.attach(null);                // 如果有旧消息的话,在下一次发送时,连同旧消息一起发送                key.attach(oldMessage != null ? oldMessage + content : content);                key.interestOps(key.interestOps() | SelectionKey.OP_WRITE);            }        }    }     private void writeMessage(SelectionKey key) throws IOException {        SocketChannel client = (SocketChannel) key.channel();        // 获取发给这个客户端的消息,并清空消息        client.write(charset.encode((String) key.attach(null)));        key.interestOps(SelectionKey.OP_READ);    }}

客户端(包含了Socket版本和SocketChannel版本):

package client; import java.io.IOException;import java.net.InetSocketAddress;import java.net.Socket;import java.net.UnknownHostException;import java.nio.ByteBuffer;import java.nio.channels.SocketChannel;import java.nio.charset.Charset;import java.util.Scanner; import constant.Constant; public class SocketClient {     public static void main(String[] args) throws IOException {        nioVersion();        // ioVersion();    }     private static void ioVersion() throws UnknownHostException, IOException {        System.out.println("客户端");        final Socket socket = new Socket();        socket.connect(new InetSocketAddress(Constant.serverPort));         new Thread() {            @Override            public void run() {                Scanner scanner = new Scanner(System.in);                 while (scanner.hasNext()) {                    String line = scanner.nextLine();                    try {                        socket.getOutputStream().write((line + "\n").getBytes("UTF-8"));                    } catch (IOException e) {                        e.printStackTrace();                    }                }                scanner.close();                try {                    socket.close();                } catch (IOException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            };        }.start();         new Thread() {            @Override            public void run() {                try {                    Scanner scanner = new Scanner(socket.getInputStream(), "utf-8");                    while (scanner.hasNext()) {                        String line = scanner.nextLine();                        System.out.println("收到消息:" + line);                    }                    scanner.close();                } catch (IOException e) {                    e.printStackTrace();                }             }        }.start();    }     private static void nioVersion() throws IOException {        Charset charset = Charset.forName("UTF-8");         System.out.println("客户端");        SocketChannel socketChannel = SocketChannel.open();        // 设置为非阻塞模式        socketChannel.configureBlocking(false);        socketChannel.connect(new InetSocketAddress(Constant.serverPort));         while (true) {            if (socketChannel.finishConnect()) {                new Thread() {                    @Override                    public void run() {                        Scanner scanner = new Scanner(System.in);                        while (scanner.hasNext()) {                            String input = scanner.nextLine();                             try {                                socketChannel.write(charset.encode(input));                            } catch (IOException e) {                                e.printStackTrace();                            }                         }                        scanner.close();                    }                }.start();                 new Thread() {                    ByteBuffer dst = ByteBuffer.allocate(1024);                     @Override                    public void run() {                        while (true) {                            try {                                int len = socketChannel.read(dst);                                if (len > 0) {                                    dst.flip();                                    System.out.println("收到消息:" + charset.decode(dst));                                    dst.compact();                                }                            } catch (IOException e) {                                // TODO Auto-generated catch block                                e.printStackTrace();                            }                        }                    }                }.start();                return;            }        }    } }

感谢你能够认真阅读完这篇文章,希望小编分享的"Java NIO怎么实现聊天室功能"这篇文章对大家有帮助,同时也希望大家多多支持,关注行业资讯频道,更多相关知识等着你来学习!

消息 客户 内容 客户端 篇文章 服务 功能 聊天室 UTF-8 事件 兴趣 同时 服务器 模式 版本 端的 系统 通道 监听 必要 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 管壳式换热器软件开发 plsql 数据库连接 嵌入式设备使用redis数据库 河北语音网络技术分类产品介绍 手机同花顺连不到服务器 新乡市新一网络技术有限公司 老版lol服务器图标 租车软件开发计划书需求分析报告 华为服务器不能设置同网段ip 建立第三方评价数据库 疫情网络安全宣传画手绘 飞瓜数据库技术 节能网络技术有哪些 免费公司软件开发 失落的方舟那个服务器好 塔式服务器功能 工业信息化部网络安全局刘超 sql数据库连接失败 书目数据库是全文数据库吗 软件开发为什么别人工资高 浙江无级互联网科技有限公司 常州小型软件开发咨询报价 互联网之光高科技博览会 软件开发人员保密管理 济南博赛网络技术公司招聘 武昌订制软件开发电话 众人网络安全技术公司怎么样 用什么软件开发手机app 计算机与网络技术的重要性 华为电信中国系统网络安全
0