NIO与BIO服务器端对比

news2024/10/7 16:22:51

本文利用NIO实现一个重复回复,客户端发送什么信息,客户端就会收到什么信息。

主要是理解NIO与BIO的区别。客户端采用telnet进行测试,以下连接是Telnet安装的方法。

Telnet的简单使用_武汉小喽啰的博客-CSDN博客_telnet

注意!!!当使勇telnet连接成功到黑屏时候一定要用ctrl +] 进入客户端

注意!!!当使勇telnet连接成功到黑屏时候一定要用ctrl +] 进入客户端

注意!!!当使勇telnet连接成功到黑屏时候一定要用ctrl +] 进入客户端

可以使用?/help 进行命令查看命令很少的。

BIO即阻塞IO测试,发现以下两个地方会被阻塞,第一个客户端连接,第二个是客户端输入信息

  • Socket socket = serverSocket.accept();
  • InputStream is = socket.getInputStream();

客户端连接服务端流程:

【第一步】启动服务器--服务器运行到accept命令阻塞

【第二步】连接客户端,服务器接收客户端,阻塞到 getInputStream() 等待客户端发送信息。

可以看出来,一个线程为客户端服务,直到客户端断开连接

【代码】

package cn.msf.bio;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @author: msf
 * @date: 2022/11/22
 */
public class BIO {
    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(10101);
            System.out.println("服务端启动");
            while (true) {
                // 获取一个套接字(阻塞)
                Socket socket = serverSocket.accept();
                System.out.println("来了一个客户端");
                hander(socket);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void hander(Socket socket) {
        byte[] bytes = new byte[1024];
        int len = 0;
        try {
            // 阻塞等待。
            InputStream is = socket.getInputStream();
            // 将信息读到bytes中。
            while ((len = is.read(bytes)) != -1) {
                System.out.println(new String(bytes, 0, len));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            System.out.println("关闭socket");
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

}

NIO实现测试

【第一步】建立服务器端,这里使用的命令是

ServerSocketChannel serverChannel = ServerSocketChannel.open();
        // 设置为不阻塞
serverChannel.configureBlocking(false);
        // 设置socket的连接接口
serverChannel.socket().bind(new InetSocketAddress("localhost",port));

【第二步】开启selector相当找了一个服务员,为客户端服务

// 启动一个选择器
        selector = Selector.open();
        serverChannel.register(selector, SelectionKey.OP_ACCEPT);

 【第三步】监听客户端连接

 public void listen() throws IOException {
        System.out.println("服务端启动成功");
        while (true) {
            // 当服务端注册的时间到达后,返回;否则会一直阻塞
            selector.select();
            selector.wakeup();
            Iterator<SelectionKey> ite = selector.selectedKeys().iterator();
            while (ite.hasNext()) {
                SelectionKey key = ite.next();
                ite.remove();
                // 处理事件的类型
                handler(key);
            }
        }
    }

【第四步】为不同客户端处理不同的事件。

可以达到一对多服务,不会想BIO一样阻塞在getinputstream哪里只等待一个客户端

 

private void handler(SelectionKey key) throws IOException {
        if (key.isAcceptable()) {
            // 说明是注册事件
            handlerAccept(key);
        } else if (key.isReadable()) {
            handlerRead(key);
        }
    }

【完整代码】 

package cn.msf.nio;

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

/**
 * @author: msf
 * @date: 2022/11/23
 */
public class NIOServer {
    private Selector selector;

    public static void main(String[] args) throws IOException {
        NIOServer server = new NIOServer();
        server.initServer(8000);
        server.listen();
    }


    public void initServer(int port) throws IOException {
        // 获得一个ServerSocket 通道
        ServerSocketChannel serverChannel = ServerSocketChannel.open();
        // 设置为不阻塞
        serverChannel.configureBlocking(false);
        // 设置socket的连接接口
        serverChannel.socket().bind(new InetSocketAddress("localhost",port));

        // 启动一个选择器
        selector = Selector.open();
        serverChannel.register(selector, SelectionKey.OP_ACCEPT);
    }

    public void listen() throws IOException {
        System.out.println("服务端启动成功");
        while (true) {
            // 当服务端注册的时间到达后,返回;否则会一直阻塞
            selector.select();
            selector.wakeup();
            Iterator<SelectionKey> ite = selector.selectedKeys().iterator();
            while (ite.hasNext()) {
                SelectionKey key = ite.next();
                ite.remove();
                // 处理事件的类型
                handler(key);
            }
        }
    }

    private void handler(SelectionKey key) throws IOException {
        if (key.isAcceptable()) {
            // 说明是注册事件
            handlerAccept(key);
        } else if (key.isReadable()) {
            handlerRead(key);
        }
    }

    public void handlerAccept(SelectionKey key) throws IOException {
        // 当有事件来了,获得之前的服务端
        ServerSocketChannel server = (ServerSocketChannel) key.channel();
        // 获得客户端的通道--相当于客户端
        SocketChannel channel = server.accept();
        channel.configureBlocking(false);
        System.out.println("客户端连接");
        channel.register(this.selector,SelectionKey.OP_READ);
    }

    private void handlerRead(SelectionKey key) throws IOException {
       // 服务器可读消息,得到事件发生的Socket通道。
        SocketChannel channel = (SocketChannel) key.channel();
        // 创建缓冲区
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        int read = channel.read(buffer);
        if (read > 0) {
            byte[] data = buffer.array();
            String msg = new String(data).trim();
            System.out.println("服务器收到消息: " + msg);
            ByteBuffer outBuffer = ByteBuffer.wrap(msg.getBytes(StandardCharsets.UTF_8));
            // 将消息发送给客户端
            channel.write(outBuffer);
        } else {
            channel.close();
        }

    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/30164.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

POSIX信号量

文章目录概念信号量函数基于环形队列的生产消费模型概念 信号量是一个计数器&#xff0c;用来描述临界资源数量的计数器。 每个执行流要进入临界资源时&#xff0c;要先申请信号量&#xff0c;出临界资源时&#xff0c;要释放信号量。 信号量的PV操作 P操作&#xff1a;申请…

万字长文总结分布式事务,总有一款适合你

导语&#xff1a;本文参考网络相关文章&#xff0c;主要总结了XA, 2PC, 3PC, 本地事务状态表, 可靠消息队列, 最大努力通知, TCC, SAGA等分布式事务的特点和适用场景&#xff0c;为大家选择分布式事务提供一些参考。 概述 分布式事务是指事务的参与者、支持事务的服务器、资源…

宝刀未老!阿里P8老兵耗时三年总结出这份Java项目实战文档

文档特点&#xff1a; 为了方便小伙伴们能更好地阅读&#xff0c;我已经提前给大家整理好了学习路线和知识结构 本书综合讲解Java程序设计中的核心技术&#xff0c;全书一共设计为22章&#xff0c;章节结构如下。 需要获取的小伙伴可以直接转发关注后私信&#xff08;学习&…

[Python]Django 配置

文章目录&#x1f349; pycharm中打开Django项目并配置虚拟环境运行项目&#x1f348; 打开项目后pycharm自动识别配置项目运行环境&#x1f34d; 指定项目运行的端口号&#x1f348; 自行配置项目的运行环境&#x1f34d; 配置项目的python解释器&#x1f34d; 配置Django项目…

本地demo服务器搭建计划——(三)rabbitmq配置中心config配置自动刷新

本章内容主要使用Spring Cloud Config来启动一个配置中心服务&#xff0c;通过Spring Cloud Bus消息总线&#xff08;依赖rabbitmq&#xff09;和Git仓库&#xff08;Gitee&#xff09;Webhook钩子函数来实现配置的自动更新&#xff08;push新的配置到gitee仓库时触发&#xff…

【英语口语】单词如何正确发音?

1. 发音基础介绍 音素&#xff1a;元音 辅音 单词&#xff1a;重音 失去爆破 浊化 三单 过去式过去分词 句子&#xff1a;语调 重音 弱读 连读 缩读 段落&#xff1a;意群 元音字母&#xff1a; A、E、I、O、U 2. 音节的定义 英语单词在发音的时候&#xff0c;不是一个字…

GD32F4(9):GD32f4出现上电不工作,必须按复位程序才能跑起来

GD32&#xff1a;上电不工作&#xff0c;需要按一下复位按键程序才能跑起来 文章目录GD32&#xff1a;上电不工作&#xff0c;需要按一下复位按键程序才能跑起来1.问题描述2. 我的调试思路2.1 第一步&#xff0c;排除电源问题2.2 第二步&#xff0c;排除复位电路的问题2.3 第三…

QUIC简介

一、概述、 QUIC&#xff08;Quick udp Internet connection&#xff09;&#xff1a;快速UDP互联网协议。相比于当前广泛应用的http2tcptls有如下优势&#xff1a; 减少三次握手及TLS握手时间&#xff1b;改进拥塞机制&#xff1b;避免队头阻塞的多路复用&#xff1b;连接迁移…

一文了解riscv软件系列之linux内核编译运行

一、交叉编译工具链的安装 【推荐阅读文章】 代码大佬的【Linux内核开发笔记】分享&#xff0c;前人栽树后人乘凉&#xff01; 一篇长文叙述Linux内核虚拟地址空间的基本概括 一文了解Linux内核的Oops 需要多久才能看完linux内核源码&#xff1f; 详细讲解磁盘及文件系统…

【antd vue pro】设置项目默认语言为中文:

文章目录一、官网文档&#xff1a;二、解决&#xff1a;1、在src\locales\index.js文件修改默认语言2、src\core\bootstrap.js文件&#xff0c;修改初始化的语言3、src\store\modules\app.js4、清空本地存储&#xff0c;然后npm run serve重启&#xff1a;5、遇到问题&#xff…

Linux文件权限管理:chomd命令和chown命令

Linux文件权限管理&#xff1a;chomd命令和chown命令前言介绍文件类型文件权限文件所属文件信息chomd命令chown命令前言 在服务器部署项目、安装应用会经常涉及到文件权限的问题&#xff0c;在此记录chomd命令和chown命令它们的用法及区别。 介绍 以下图为例&#xff0c;进行…

如何解决全局工业相机飞拍拖影问题

1.问题描述: 物体静态拍摄时图像正常&#xff0c;但是动态拍摄时会有拖影现象。 2.问题原因&#xff1a; 只要物体存在运动&#xff0c;拍摄就一定会存在拖影&#xff0c;那么如何判断飞拍项目能否使用&#xff1f;拖影是否会对飞拍造成影响呢&#xff1f;这就要看具体的检测…

Viterbi维特比译码误码率仿真,调制为QPSK,信道为高斯白噪声

目录 1.算法描述 2.仿真效果预览 3.MATLAB部分代码预览 4.完整MATLAB程序 1.算法描述 整体思路如图1中所示&#xff0c; 其中输入序列使用randn函数来产生&#xff0c;卷积也采用matlab本身的函数conv&#xff0c;加性高斯白噪声用wgn函数来产生&#xff0c;由于实验的重点…

世上最全NVDIA GPU参数列表: 3090,4090, A40, A30,V100, A100, A800性能参数

-1&#xff09;GeForce RTX 4090 GeForce RTX 4090 GPU 引擎规格&#xff1a;NVIDIA CUDA 核心数量16384加速频率 (GHz)2.52基础频率 (GHz)2.23显存规格&#xff1a;标准显存配置24 GB GDDR6X显存位宽384 位技术支持&#xff1a;Ray Tracing Core第 3 代Tensor Cores第 4 代N…

CRDB-多区域部署

多区域部署允许cockachdb数据库跨越多个地理区域。多区域部署的配置对集群的容错和区域性能有影响。一般来说&#xff0c;我们将一个cockachdb集群配置为多个区域&#xff0c;以实现以下两个目标中的一个或两个&#xff1a; 允许集群在其中一个区域的计算资源不可用时继续服务…

磨金石教育摄影技能干货分享|花朵怎样拍才能不凌乱

喜欢养花种花的朋友&#xff0c;除了享受花朵在自己精心培育下绽放之外&#xff0c;给爱花拍照发在朋友圈炫耀也是一大乐趣之一。 但是别看花朵静静地盛开&#xff0c;娇艳欲滴&#xff0c;想要拍得好看却不是一件容易的事。作为摄影小白常常遇到的情况就是&#xff0c;拍出的花…

即兴发言怎样避免语无伦次?记住这个即兴发言万能公式

作为PMO和项目经理&#xff0c;经常要组织和参与各种会议&#xff0c;在会议中难免需要即兴发言&#xff0c;但是很多人即兴发言时总语无伦次&#xff0c;不知所云&#xff0c;而PMO和项目经理又是依靠外在表现来体现自己的专业性的&#xff0c;这时候就很难获得被人的认可&…

Docker Desktop Installer 安装无反应的,如何解决?

docker教程 Docker 教程 | 菜鸟教程 下载地址&#xff1a; Docker Desktop 官方下载地址&#xff1a; Install on Windows | Docker DocumentationHow to install Docker Desktop for Windowshttps://docs.docker.com/desktop/install/windows-install/ 问题&#xff1a;出…

webpack

webpack一、前端工程化1、前端开发历程2、什么是前端工程化3、前端工程化的解决方案二、webpack的基本使用1、什么是webpack2、列表隔行变色例子3、安装和配置webpack1.安装webpack2.配置webpack4、webpack.config.js的作用5、配置webpack.config.js自定义打包入口和出口三、we…

乘用车排气系统流场的数值模拟

目 录 摘 要 I Abstract II 第1章 绪论 1 1.1 课题背景及意义 1 1.2 国内外研究现状 1 1.3 课题主要研究内容 2 第2章 流体力学及流场分析软件的介绍 4 2.1 概述 4 2.2 流体力学及应用现状 4 2.3 Solidworks软件的应用范围 5 2.4 Flow Simulation 软件简介 5 第3章 排气系统理论…