使用原生NIO实现一个echo服务器

【NIO】更简单的nio使用方式 接触nio也有好几年了,最开始摸不着头脑,资料很少,网上的资料都是翻来覆去的抄袭,基本上对于自己的学习没有大帮助。 后来遇到了xsocket,觉得用起来还可以,挺方便,api也很简洁。不过这个库的用户不多,后来作者也停止了开发。 然后就是mina netty,这些不用说,了解nio的人都知道它们。不过想用好它们也不是那么容易。里面有各种回调,各种future,当你在处理网络事件 阅读详情

tcp的拆包处理使用的是定长解码的方式。
服务器端:

public class EchoServer {
    public static final int port = 8888;

    public static void main(String[] args) throws IOException {
        Selector selector = Selector.open();

        ServerSocketChannel listener = ServerSocketChannel.open();
        // 绑定地址,并监听
        listener.socket().bind(new InetSocketAddress("localhost", port));

        // 设置非阻塞
        listener.configureBlocking(false);
        // 注册ACCPET事件
        listener.register(selector, SelectionKey.OP_ACCEPT);
        NIOServerConnection conn;
        while (true) {
            // 每1秒选择一次
            if (selector.select(1000) == 0) {
                System.out.print(".");
                continue;
            }

            Iterator<SelectionKey> iter = selector.selectedKeys().iterator();

            while (iter.hasNext()) {
                SelectionKey key = iter.next();
                iter.remove();
                if (key.isAcceptable()) {
                    listener = (ServerSocketChannel) key.channel();
                    SocketChannel clientChannel = listener.accept();
                    // 设置地址复用
                    clientChannel.socket().setReuseAddress(true);
                    clientChannel.configureBlocking(false);
                    // 将接受的客户端通道设置可读
                    SelectionKey connKey = clientChannel.register(selector, SelectionKey.OP_READ);
                    // 使用该类处理读写请求
                    conn = new NIOServerConnection(connKey);
                    connKey.attach(conn);
                }

                if (key.isReadable()) {
                    conn = (NIOServerConnection) key.attachment();
                    conn.handleRead();
                }

                if (key.isValid() && key.isWritable()) {
                    conn = (NIOServerConnection) key.attachment();
                    conn.handleWrite();
                }

            }
        }

    }
}

服务器端处理读写类:

public class NIOServerConnection {
    private final SelectionKey key;
    private ByteBuffer data;
    private final ByteBuffer dataLengthBuffer;

    public NIOServerConnection(SelectionKey key) {
        this.key = key;
        dataLengthBuffer = ByteBuffer.allocate(4);
    }

    public void handleRead() {
        dataLengthBuffer.clear();
        SocketChannel channel = (SocketChannel) key.channel();
        try {
            long bytesRead = channel.read(dataLengthBuffer);
            assert bytesRead == 4;
            // 标记一下
            dataLengthBuffer.flip().mark();
            int len = dataLengthBuffer.getInt();
            // 在读取的时候,还要重置的
            dataLengthBuffer.reset();
            data = ByteBuffer.allocate(len);
            bytesRead += channel.read(data);
            // 断言全部读取完毕
            assert bytesRead == (4 + len);
            byte[] b = data.array();
            int port = channel.socket().getPort();
            System.out.println("client port : " + port + " ; msg : " + new String(b));
            if (bytesRead == -1) {
                channel.close();
            } else {
                key.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE);
            }
        } catch (IOException e) {
            e.printStackTrace();
            try {
                channel.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
    }

    public void handleWrite() {
        data.flip();
        SocketChannel channel = (SocketChannel) key.channel();
        try {
            channel.write(new ByteBuffer[] { dataLengthBuffer, data });
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (!data.hasRemaining())
            key.interestOps(SelectionKey.OP_READ);
        data.compact();
    }

}

客户端:

/**
 * @author root TCP NIO 定长拆包
 */
public class EchoClient {
    public static final String[] messages = new String[] { "nio", "netty", "love", "java", "learn" };
    public static final Random rand = new Random();
    public static final String BLANK = " ";

    public static String getMsg() {
        StringBuilder msg = new StringBuilder();
        int len = messages.length;
        int words = rand.nextInt(len) + 1;
        for (int i = 0; i < words; i++) {
            msg.append(messages[rand.nextInt(len)] + BLANK);
        }
        return msg.toString() + getDate();
    }

    public static String getDate() {
        Date date = new Date();
        return date.toString();
    }

    public static void main(String[] args) {
        SocketChannel clientChannel = null;
        try {
            Selector selector = Selector.open();
            clientChannel = SocketChannel.open();
            clientChannel.connect(new InetSocketAddress("localhost", EchoServer.port));
            clientChannel.configureBlocking(false);
            SelectionKey key = clientChannel.register(selector, SelectionKey.OP_WRITE);
            NIOClientConnection conn = new NIOClientConnection(key);
            key.attach(conn);
            while (true) {
                Thread.sleep(2000);
                selector.select();
                Iterator<SelectionKey> iters = selector.selectedKeys().iterator();
                while (iters.hasNext()) {
                    key = iters.next();
                    iters.remove();
                    if (key.isWritable()) {
                        conn = (NIOClientConnection) key.attachment();
                        conn.doWrite(getMsg());
                    }
                    if (key.isReadable()) {
                        conn = (NIOClientConnection) key.attachment();
                        conn.doRead();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            try {
                clientChannel.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
    }

}

客户端处理读写类:

public class NIOClientConnection {
    private final SelectionKey key;
    private ByteBuffer data;
    private final ByteBuffer dataLengthBuffer;

    public NIOClientConnection(SelectionKey key) {
        this.key = key;
        dataLengthBuffer = ByteBuffer.allocate(4);
    }

    public void doWrite(String msg) {
        dataLengthBuffer.clear();
        byte[] b = msg.getBytes();
        int len = b.length;
        // put操作后需要flip,wrap操作不用flip
        dataLengthBuffer.putInt(len);
        dataLengthBuffer.flip();
        data = ByteBuffer.wrap(b);
        SocketChannel channel = (SocketChannel) key.channel();
        try {
            System.out.println("send => " + msg);
            long bs = channel.write(new ByteBuffer[] { dataLengthBuffer, data });
            if (bs == 0)
                channel.close();
            else
                key.interestOps(SelectionKey.OP_READ);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void doRead() {
        dataLengthBuffer.clear();
        data.clear();
        SocketChannel channel = (SocketChannel) key.channel();
        try {
            long bs = channel.read(new ByteBuffer[] { dataLengthBuffer, data });
            if (bs == 0 || bs == -1) {
                return;
            }
            dataLengthBuffer.flip();
            int len = dataLengthBuffer.getInt();
            byte[] buf = data.array();
            assert len + 4 == bs;
            System.out.println("receive => " + new String(buf));
            key.interestOps(SelectionKey.OP_WRITE);
        } catch (IOException e) {
            e.printStackTrace();
            try {
                channel.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
    }
}

测试:
服务器结果:
这里写图片描述
客户端:
这里写图片描述

模仿echo命令学习NIO——Java实现 一、NIO模型:同步非阻塞IO处理 在传统的Java环境里面,最初的程序需要依赖于JVM虚拟机技术。最早的时候由于虚拟机的性能较差,所以很少有人去关注通讯的速度问题,大部分的问题都出现在了CPU处理上。 但是随着硬件的性能提升,实际上CPU的处理速度加强了。所以从JDK 1.4开始就引入NIO的开发包,可以带来底层数据的传输性能。 在NIO之中采用了一个Reactor事件模型,注册的汇集点Sele... 阅读详情

相关推荐

采用NIO实现一个Socket服务器

NULL 博文链接:https://wjy320.iteye.com/blog/2002237

使用 NIO 实现 echo 服务器

NIO相关知识点IO、NIO、AIO 内部原理分析 NIO 之 Selector实现原理 NIO 之 Channel实现原理 NIO 之 ByteBuffer实现原理服务器使用NIO来实现一个echo协议的服务器。 echo协议简单也很有用,可以测试网络连接。消息的格式为:消息长度(int)+消息内容通过消息长度来进行socket分包,防止读取出现半包、粘包等问题。服务端import jav

jijianshuai的专栏 1961

Linux socket编程实例:echo服务器程序

Linux socket编程实例:echo服务器程序

使用NIO实现一个echo服务器

    一个简单的echo服务器,客户端向服务端发送消息,服务端进行响应,当客户端发送quit字符串时,断开客户端和服务端的连接。使用NIO实现    服务端代码public class EchoServer_NIO { private Selector selector; private ByteBuffer sendBuf = ByteBuffer.allocate(1024)...

yanghan1222的博客 810

NIO(java)原生实现,没有用任何框架

java nio 的服务端完整实现,应该可以商用,但我没有真实投入商用,就是一个学习过程的总结,代码应该算是很完整,对学习nio应该是很有帮助,而且没有使用任何框架,但借鉴了很多框架的核心代码。

从公式到实践:用SPSS解锁香农多样性指数的生态洞察

本文详细介绍了如何利用SPSS软件计算和应用香农多样性指数进行生态研究。从基础公式解析到SPSS实战操作,再到生态决策支持,全面展示了该指数在物种丰富度和均匀度量化中的价值。文章特别强调了SPSS操作中的关键技巧和常见误区,为生态研究者提供了一套完整的分析解决方案。

weixin_30832143的博客 465

[转]用nio实现Echo服务

[转]http://finux.iteye.com/blog/368955   今天突然间想用nio实现个Echo服务,程序实现起来实现不算困难,但跑起来后,在Server端的ServerSocket完成accept之后,我的CPU总是跳到100%。嗯,小郁闷,后来,才发现自己在Server端注册了多余的监听事件SelectionKey.OP_WRITE,改过来后好多了,希望记住这个教训。 ...

caoruntaogmail的博客 167

ifix5.8连接ab plc的点-通过rslinx

以ifix连接ab plc的点为例 1.先在rslinx上把plc的点导出为opc server 2.使用opc power tool 作为opc client 去连接 3.保存到项目的PDB文件夹下面,并且以节点名命名。 也可以不以节点名命名,系统自动会生成一个以节点名命名的这种文件,就显得很乱。 同时,项目的PDB目录下面必须还得拷过来一个de...

中国智造2025 4110

Android与Java NIO实现简单Echo服务器与客户端

上一篇用Java IO来做了个Demo,于是乎进一步,用Java NIO来做一个。NIO的优势在于非阻塞。使用了Selector在一个线程里进行轮询,就能够完成接入、收\发消息的操作,不需要每建立一个连接都新启动一个线程的方式。Server端代码:public class EchoServer { private static final int MAX_SIZE = 256; // ma...

zyh9018的专栏 950

FPGA实战:手把手教你实现雷达信号数字下变频(DDC)完整流程

本文提供了一份完整的FPGA实现雷达信号数字下变频(DDC)的实战指南。内容涵盖从Matlab行为级仿真到FPGA硬件实现的完整闭环流程,详细讲解了数字混频、滤波、抽取等核心步骤,并分享了基于Vivado的IP核配置、数据位宽量化及资源优化等关键工程实践经验,旨在帮助读者掌握DDC系统的硬件实现与调试。

dog123的博客 341

向量数据库安全实战:从Embedding反推到检索越权的全链路防护

随着RAG应用在企业中的普及,向量数据库已成为知识库系统的核心组件。但许多团队对向量数据的安全认知仍停留在传统数据库的账号密码、网络隔离和磁盘加密上。事实上,向量化并非加密,而是一种有损压缩的语义映射,向量本身可以被反推模型还原出原文关键信息,形成高保真的语义泄露通道。同时,相似度检索的模糊匹配特性打破了传统行列权限模型,使得越权检索和成员推断攻击成为新的安全威胁。理解这些原理,有助于企业在数据采集、向量化、索引构建、检索查询等环节构建分层防护体系,包括脱敏、扰动、过滤下推、网关控制等手段。本文从基础概念出

weixin_29323551的博客 259

Java中的BIO,NIO,AIO详解以及Echo实现示例

Abstract 在本博客当中我们主要会分为如下几点: Java中的BIO NIO AIO是啥 BIO NIO AIO实现的简单Echo client和server NIO AIO 深入之内部实现 NIO AIO的设计模式: Reactor 以及 Proactor 本文所有的代码都可以在最后的github找到. IO 的分类 BIO BIO 是 blocking io, 在jdk1.0的时候引...

scugxl的专栏 2882

解决西门子Step 7 basic 找不到许可证问题

你在使用博图软件是否遇到过Step 7 basic 找不到许可证的问题呢!不言怕,今天我就来告诉你该如何处理吧!看步骤: 1.删除原授权的License: 打开Automation License Manager应用,然后我们可以发现仅有的License Key前面有一个时钟,说明它已经过期不可用,我们就要去寻求新的Key. 打开“我的电脑”,选择C盘,点击上方查看 点击选项–>查看 然...

让技术没有门槛 14万+

Netty vs NIO:为什么大厂都在用Netty做网络编程?

本文深入对比了Netty与原生Java NIO在网络编程中的优劣。Netty作为基于NIO构建的高性能客户端-服务器框架,通过其主从多Reactor线程模型、高效的ByteBuf内存管理以及Pipeline与Handler链等核心组件,极大地简化了高并发网络应用的开发,解决了NIO在API复杂性、线程模型、粘包拆包处理及资源管理等方面的痛点,因此成为阿里巴巴、gRPC等大厂构建分布式系统的首选。

uuu88的博客 205

基于STM32L4XX 、HAL库的TMC2226-SA-T步进电机驱动器驱动程序应用设计

集成的功率MOSFET可处理高达2A RMS的电机电流,并具备保护与诊断功能,确保运行稳健可靠。作为业界最先进的STEP/DIR步进电机驱动系列,该芯片通过升级设计实现无噪音、高精度运行,为用户提供高性价比且极具竞争力的解决方案。// 用于PDN_UART单线通信。// HAL_UART_Transmit - 注意PDN_UART是单线,收发共线。.huart = &huart1, // PDN_UART连接的USART。均方根步进/方向控制接口,提供8、16、32或64微步针设置,

PP_Cottage的博客 621

别再盯着那 100 条数据了,RAP OData 分页机制到底在保护什么

摘要: SAP BTP ABAP Environment 的 OData 服务默认采用分页保护机制,未指定 $top 时仅返回100条数据并附带下一页链接。这种设计旨在防止资源滥用,而非服务故障。客户端应遵循OData协议规范,直接使用服务端返回的 next link 进行分页请求,而非自行构造URL。当指定 $top 参数时,若数值超过5000仍会被强制分页。该机制在SAPUI5控件中被自动处理,但自定义客户端需主动实现分页逻辑。对于自定义实体(Custom Entity),开发者需在Query Prov

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 859

Netty 是什么?一文带你彻底搞懂高性能网络编程框架(附 Spring Boot 集成实战)

Netty = 高性能网络编程的瑞士军刀原生 NIO 太底层,Netty 让你专注业务在 Spring Boot 中集成 Netty,生命周期交由容器管理更安全不要阻塞 I/O 线程、注意内存释放、合理使用线程模型视频看了几百小时还迷糊?关注我,几分钟让你秒懂!

qq_45202803的博客 1491

YOLOv12中的A2C2f模块详解,涉及区域注意力模块(A2)和 R-ELAN 结构详解

区域注意力模块(Area Attention, A2)的设计出发点是为了解决传统注意力机制在计算复杂度和内存访问效率上的问题。传统的自注意力机制(Self-Attention)具有二次方的计算复杂度(O(n²)),尤其是在处理高分辨率图像时,计算成本非常高。此外,注意力机制的内存访问模式不如卷积神经网络高效,导致在实际应用中难以满足实时性要求。区域注意力模块通过将特征图划分为多个区域,并在每个区域内进行注意力计算,从而显著降低了计算复杂度。

Limiiiing的博客 5513

Kotlin NIO 实现非阻塞echo服务器

传统的阻塞式方案通常在有新的链接时使用其他线程进行处理,每个线程负责处理一个socket,如 ServerSocket serverSocket = new ServerSocket(3000); while(true){ Socket socket = serverSocket.accept(); new Thread(()->{ ///socket.getI

weixin_52534279的博客 2086

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

java echo 服务器_分别使用Java IO、NIO、Netty实现的一个Echo Server示例

分别使用Java IO、Java NIO、Netty来实现一个简单的EchoServer(即原样返回客户端的输入信息)。Java IOintport=9000;ServerSocketss=newServerSocket(port);while(true){finalSocketsocket=ss.accept();newThread(newRunnable(){p...

weixin_42412396的博客 191

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

JavaNIO--2.实现ECHO服务器

JavaNIO技术实现ECHO服务器 1.NIO核心组件的使用 1.1初始化NIO组件 1.2Accept组件 1.3SelectLoop(核心组件) 2.NIO通道读写(Buffer) 2.1读取通道内容 2.2Buffer处理辅助方法 3.测试结果 4.完整代码 JavaNIO技术实现ECHO服务器 所谓ECHO服务器就是客户端发送到服务器端什么内容,服务器端就返回...

CringKong的博客 942

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Netty如何写一个 echo 服务器

Netty如何写一个 echo 服务器 由YmKK创建, 最后一次修改2017-08-02 Netty 实现的 echo 服务器都需要下面这些: 一个服务器 handler:这个组件实现了服务器的业务逻辑,决定了连接创建后和接收到信息后该如何处理 Bootstrapping: 这个是配置服务器的启动代码。最少需要设置服务器绑定的端口,用来监听连接请求。 通过 ChannelHandl...

拼命小孩的成长专栏 265

Netty编写Echo服务器

本文介绍了使用Netty框架实现Echo服务器的全过程。服务器端采用主从Reactor线程模型,创建bossGroup(负责连接)和workerGroup(处理I/O)两个事件循环组,通过ServerBootstrap配置NIO通道、编解码器(StringDecoder/StringEncoder)和业务处理器(EchoServerHandler)。客户端使用Bootstrap配置类似组件(EchoClientHandler)。服务端收到消息后会原样返回,展示了Netty的基本网络通信流程。

tanxinji的博客 799

Echo服务

Echo服务作为最基本的网络服务之一,具有重要的学习和实践价值。通过实现BIO、NIO和Netty版本的Echo服务,开发者可以深入理解不同I/O模型的工作原理及其适用场景。BIO模式:适用于简单的低并发场景,但无法满足高并发需求。NIO模式:通过非阻塞I/O和多路复用,提高了系统的并发处理能力,适合高并发场景。Netty模式:在NIO基础上进行了高度封装,提供了强大的功能和更高的性能,是构建高性能网络应用的理想选择。

Flying_Fish_roe的博客 1124

Netty从0到1系列之NIO

NIO核心思想与组件摘要 传统BIO采用阻塞式流模型,存在线程资源浪费问题。NIO通过三大核心组件实现高效I/O处理: Channel:双向通信通道(文件/网络),支持非阻塞模式 Buffer:数据容器,通过position/limit/capacity机制实现灵活读写 Selector:多路复用器,单线程可监控数千通道的IO事件

编程技术圈 1460

使用nio实现简单Echo服务

最近温习下nio API,无聊写个Echo服务,直接上代码了,有点懒,具体细节不解释,查阅API或源码吧,没有公开的src就反编译下。   EchoServer.java   package com.iteye.finux.echo; import java.io.IOException; import java.net.InetAddress; import java.net....

zhuxianfeng的专栏 244
上一篇: 最新版Spark2.2读取多种文件格式数据
下一篇: 使用BlockingQueue查找某个文件夹下的所有文本文件中是否包含文字
Next__One
博客等级 码龄9年 14粉丝 62原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值