java基于NIO实现群聊模式

yizhihongxing

Java基于NIO实现群聊模式攻略

简介

Java NIO(New I/O)是Java 1.4版本引入的一组用于高效处理I/O操作的API。使用Java NIO,我们可以实现非阻塞的、事件驱动的I/O操作,这对于实现群聊模式非常有用。在本攻略中,我们将使用Java NIO来实现一个简单的群聊程序。

步骤

步骤1:创建服务器端

首先,我们需要创建一个服务器端来接收客户端的连接,并将接收到的消息广播给所有连接的客户端。

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

public class Server {
    private Selector selector;
    private ServerSocketChannel serverSocketChannel;
    private ByteBuffer buffer = ByteBuffer.allocate(1024);

    public void start(int port) throws IOException {
        selector = Selector.open();
        serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.bind(new InetSocketAddress(port));
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        System.out.println(\"Server started on port \" + port);

        while (true) {
            selector.select();
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();
                iterator.remove();

                if (key.isAcceptable()) {
                    acceptConnection(key);
                } else if (key.isReadable()) {
                    broadcastMessage(key);
                }
            }
        }
    }

    private void acceptConnection(SelectionKey key) throws IOException {
        ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
        SocketChannel clientChannel = serverChannel.accept();
        clientChannel.configureBlocking(false);
        clientChannel.register(selector, SelectionKey.OP_READ);
        System.out.println(\"New client connected: \" + clientChannel.getRemoteAddress());
    }

    private void broadcastMessage(SelectionKey key) throws IOException {
        SocketChannel clientChannel = (SocketChannel) key.channel();
        buffer.clear();
        int bytesRead = clientChannel.read(buffer);
        if (bytesRead == -1) {
            clientChannel.close();
            return;
        }
        buffer.flip();
        byte[] bytes = new byte[buffer.remaining()];
        buffer.get(bytes);
        String message = new String(bytes);
        System.out.println(\"Received message: \" + message);

        for (SelectionKey selectionKey : selector.keys()) {
            Channel channel = selectionKey.channel();
            if (channel instanceof SocketChannel && channel != clientChannel) {
                SocketChannel destChannel = (SocketChannel) channel;
                destChannel.write(ByteBuffer.wrap(bytes));
            }
        }
    }

    public static void main(String[] args) throws IOException {
        Server server = new Server();
        server.start(8080);
    }
}

步骤2:创建客户端

接下来,我们需要创建一个客户端来连接服务器,并发送和接收消息。

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Scanner;

public class Client {
    private SocketChannel socketChannel;
    private ByteBuffer buffer = ByteBuffer.allocate(1024);

    public void start(String serverHost, int serverPort) throws IOException {
        socketChannel = SocketChannel.open();
        socketChannel.configureBlocking(false);
        socketChannel.connect(new InetSocketAddress(serverHost, serverPort));

        while (!socketChannel.finishConnect()) {
            // 等待连接完成
        }

        System.out.println(\"Connected to server: \" + socketChannel.getRemoteAddress());

        new Thread(() -> {
            try {
                while (true) {
                    buffer.clear();
                    int bytesRead = socketChannel.read(buffer);
                    if (bytesRead == -1) {
                        socketChannel.close();
                        return;
                    }
                    buffer.flip();
                    byte[] bytes = new byte[buffer.remaining()];
                    buffer.get(bytes);
                    String message = new String(bytes);
                    System.out.println(\"Received message: \" + message);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();

        Scanner scanner = new Scanner(System.in);
        while (true) {
            String message = scanner.nextLine();
            if (message.equalsIgnoreCase(\"exit\")) {
                socketChannel.close();
                break;
            }
            buffer.clear();
            buffer.put(message.getBytes());
            buffer.flip();
            socketChannel.write(buffer);
        }
    }

    public static void main(String[] args) throws IOException {
        Client client = new Client();
        client.start(\"localhost\", 8080);
    }
}

示例说明

示例1:运行服务器端

Server server = new Server();
server.start(8080);

示例2:运行客户端

Client client = new Client();
client.start(\"localhost\", 8080);

在示例2中,客户端将连接到本地主机的8080端口,并可以发送和接收消息。在服务器端示例1中,服务器将监听8080端口,并将接收到的消息广播给所有连接的客户端。

请注意,示例中的代码仅为演示目的,可能需要根据实际需求进行修改和扩展。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java基于NIO实现群聊模式 - Python技术站

(0)
上一篇 2023年7月29日
下一篇 2023年7月29日

相关文章

  • php md5下16位和32位的实现代码

    PHP MD5算法 MD5(Message Digest Algorithm 5)是一种常用的哈希算法,用于将任意长度的数据转换为固定长度的哈希值。在PHP中,可以使用内置的md5()函数来计算MD5哈希值。 16位MD5哈希值 要获取16位的MD5哈希值,可以通过截取32位MD5哈希值的一部分来实现。下面是一个示例代码: <?php function…

    other 2023年7月28日
    00
  • thinkphp实现无限分类(使用递归)

    今天我将会为大家详细讲解如何使用ThinkPHP框架实现无限分类功能,包括使用递归方法和两条示例说明。 步骤1:创建分类表 首先,我们需要在数据库中创建分类表,该表需要包含以下字段: id: 分类ID pid: 上级分类ID name: 分类名称 可以通过以下SQL语句来创建该表: CREATE TABLE `category` ( `id` int(10)…

    other 2023年6月27日
    00
  • 实例讲解DataTables固定表格宽度(设置横向滚动条)

    下面是详细讲解“实例讲解DataTables固定表格宽度(设置横向滚动条)”的完整攻略和两条示例说明: 简介 在进行数据表格展示时,如果数据过多,表格宽度往往会超过页面宽度,导致页面布局混乱,不方便查看数据。针对这种情况,可以借助DataTables的宽度设置功能,将表格宽度进行限制,并设置横向滚动条,从而更好地展示数据。 实现方法 1. 基本宽度设置 在初…

    other 2023年6月27日
    00
  • 怎样让网站的关键词排名更安稳?长期稳定网站排名六大技巧

    怎样让网站的关键词排名更安稳?长期稳定网站排名六大技巧 在优化网站关键词排名的过程中,我们希望能够实现长期的稳定性。下面是六个技巧,可以帮助你达到这个目标。 1. 优化网站内容 确保网站内容与关键词相关性高:将关键词自然地融入网站内容中,但不要过度堆砌关键词。 提供有价值的内容:确保网站内容对用户有帮助,能够解决他们的问题或提供有用的信息。 定期更新网站内容…

    other 2023年9月6日
    00
  • WPF自定义控件的实现

    实现一个自定义控件需要以下步骤: 第一步:创建控件项目 我们需要在Visual Studio中添加一个WPF Custom Control项目。这个项目将包含一个基本的自定义控件,它是在WPF控件库中支持的标准控件的基础上构建的。 第二步:设计控件外观和交互 首先,我们需要定义自定义控件的外观和行为,这涉及到控件的布局、样式和模板。我们可以使用XAML来描述…

    other 2023年6月25日
    00
  • oppo reno反复自动重启怎么解决?

    Oppo Reno自动重启解决攻略 原因分析 Oppo Reno自动重启的原因可能是系统bug、应用冲突、系统升级问题等,需要对具体原因进行分析。 解决方案 以下是解决该问题的几种方案,可以依次尝试,可根据具体情况选择。 方案一:安全模式 进入安全模式,如果无法在安全模式下看到自动重启,可能是因为第三方应用程序引起的。尝试卸载可能引起该问题的应用程序。以下是…

    other 2023年6月27日
    00
  • asp.net TreeView递归循环子节点生成树形菜单实例

    下面我将详细讲解如何使用 asp.net TreeView 递归循环子节点生成树形菜单的完整攻略: 1. 准备工作 首先需要了解以下几点: asp.net TreeView控件是一个树形控件,它允许您在Web应用程序中创建树形菜单。 树形菜单的每个节点都可以包含文本、图像和子菜单项。 使用递归方法可以方便地生成树状结构,这样可以使代码更加简洁和易于维护。 2…

    other 2023年6月27日
    00
  • Java类加载机制实现流程及原理详解

    Java类加载机制实现流程及原理详解 Java类加载机制是Java编译器实现跨平台的核心组成部分,本篇文章将对Java类加载机制的实现流程和原理进行详解。 Java类加载机制的定义 Java编译器将程序代码编译为字节码,并将其放置在class文件中。在程序运行时,Java虚拟机通过Java类加载机制将.class文件中的字节码加载到内存中,并转换成可执行代码…

    other 2023年6月27日
    00
合作推广
合作推广
分享本页
返回顶部