当前位置: 首页 > news >正文

netty入门-5 ServerBootstrap与Bootstarp

前言

本来这篇应该紧接着说明FuturePromise
但是考虑前文第三篇即用到了ServerBootstrap来启动一个服务器,并且我读的闪电侠netty,先写的服务器与客户端启动这部分。索性就先写出来了。主要内容来自闪电侠netty

ServerBootstrap

ServerBootstrap就是一个辅助我们把服务器拉起来的辅助类,怎么用直接看下面。

服务器编写

解释全写在注释里,方便看。
示例程序是书里的。

public class NettyServer{public static  void  main(String[] args){//下面我们可以看到用了两个EventLoopGroup,一个作为boss,一个作为worker。//boss内的EventLoop负责处理连接请求。//worker中则是负责连接后的channel的io请求处理。NioEventLoopGroup  bossGroup  =  newNioEventLoopGroup();NioEventLoopGroup  workerGroup  =  newNioEventLoopGroup();ServerBootstrap  serverBootstrap  =  newServerBootstrap();serverBootstrap.group(bossGroup,  workerGroup)//给服务器指定boss和worker。两个线程组职能分离.channel(NioServerSocketChannel.class)//这里使用NIO类型的ServerSocketChannel。也有其他类型,不过常用NIO类型的。//childHandler之前第三篇文章说过,child指代ServerSocketChannel处理连接请求后产生的新的SocketChannel,所以childHandler表示对服务器连接的Channel添加的处理器。也即对Channel的数据读写如何进行处理。第三篇文章讲到了。.childHandler(newChannelInitializer<NioSocketChannel>(){protectedvoid  initChannel(NioSocketChannel  ch){}})//绑定一个端口serverBootstrap.bind(8000);}
}

梳理一下就是用ServerBootstrap 类,指定groupIo模型channel),写新连接的读写处理逻辑,绑定端口。

这里注意bind操作是一个异步操作
且我们要绑定的端口可能已经被其他应用占用了。所以需要我们递增寻找一个没有被占用的端口。
我们在第四篇文章中说到有这个ChannelFuture处理异步结果。
而这个bind也是一个异步操作,也会返回一个ChannelFuture
我们正好可以对bind操作产生的`ChannelFuture添加一个回调,来进行递增寻找端口的操作。

端口递增绑定

比如端口9000被占用了,我们要继续去bind 9001,直到找到一个可用端口。

//下面代码是一个框架,可以通过future的状态来做不同处理(关于future的状态,下篇来讲,这里可以理解为通过isSuccess()可以了解到bind操作是否成功)
//成功不用多说,失败了就要递增访问端口号。
serverBootstrap.bind(8000).addListener((ChannelFutureListener) future -> {if(future.isSuccess()){}else{serverBootstrap.bind(8001);}
})//书里这个代码挺妙的
//我们发现直接在else部分写一个bind操作似乎不行,因为这个bind操作做完失败的话我们就没有后续了。
//抽象一下,似乎无限复制代码在else部分再写一个bind(8000).addListener..,然后在其内部再写一个逻辑判断,再进行bind。
//失败就不断调用本身,递归思想private static void Bind(ServerBootstrap serverBootstrap, int port){serverBootstrap.bind(8000).addListener((ChannelFutureListener) future -> {if(future.isSuccess()){system.out.println("端口 " + port +"绑定成功" );}else{system.out.println("端口 " + port +"绑定失败" );Bind(serverBootstrap,port+1);	}})
} 

其他方法

这些方法课上确实没咋说,书里这里带了一笔。

//handler方法,和上文的childHandler一样,第三篇文章说到了。
//childHandler用于给新Channel指定读写操作的处理逻辑
//handler就是给服务器启动过程指定一些逻辑。通常用不到
serverBootstrap.handler(newChannelInitializer<NioServerSocketChannel>(){protected void initChannel(NioServerSocketChannel  ch)  {System.out.println("服务端启动中")}
})//attr和childAttr两个方法都是给Channel添加一个键值对。attr是给ServerSocketChannel的。childAttr是给所有正常连接channel的。
//即Channel内部会维护一个Map存储这些键值对。要取可以再用attr或者childAttr,根据键来取属性值
serverBootstrap.attr(AttributeKey.newInstance("serverName"),  "nettyServer")
serverBootstrap.childAttr(AttributeKey.newInstance("clientKey"),  "clientValue")//option和childOption方法是设置TCP参数的。
//同样一个针对ServerSocketChannel。childOption针对其他正常连接channel
//书中给了几个例子
serverBootstrap
//表示系统用于临时存放已完成三次握手的请求的队列的最大长度,如果连接建立频繁,服务器处理创建新连接较慢,则可以适当调大这个参数。
.option(ChannelOption.SO_BACKLOG,  1024)
//ChannelOption.SO_KEEPALIVE表示是否开启TCP底层心跳机制,true表示开启。
.childOption(ChannelOption.SO_KEEPALIVE,  true)
//ChannelOption.TCP_NODELAY表示是否开启Nagle算法,true表示关闭,false表示开启。通俗地说,如果要求高实时性,有数据发送时就马上发送,就设置为关闭;如果需要减少发送次数,减少网络交互,就设置为开启。
.childOption(ChannelOption.TCP_NODELAY,  true)

Bootstarp

ServerBootstrap类似,不过Bootstrap是用于启动客户端的辅助类。

客户端启动

同样是指定线程模型(group),IO模型(NioSocketChannel),IO操作处理逻辑(handler)。
其实同服务器启动基本一致。
不过这里书里提到了连接失败的重试处理。我们来看看

NioEventLoopGroup  workerGroup  =  newNioEventLoopGroup()Bootstrap  bootstrap  =  newBootstrap();
bootstrap
//  1.指定线程模型
.group(workerGroup)
//  2.指定IO  类型为NIO
.channel(NioSocketChannel.class)
//  3.IO 处理逻辑
.handler(newChannelInitializer<SocketChannel>(){@Overridepublicvoid  initChannel(SocketChannel  ch){}
});
//  4.建立连接
bootstrap.connect("juejin.cn",  80).addListener(future  ->if(future.isSuccess()){System.out.println("连接成功!");}else{System.err.println("连接失败!");}
});
//我们见到与上面服务器创建时,我们要做端口递增绑定类似的部分。
//这里原理类似,因为connect与bind都是异步方法,所以我们要写好异步回调,表明在异步操作成功后做什么,失败后做什么
//connect失败说明连接失败。我们可以用重试,一定次数后放弃连接,并且不会在失败后立即重连,指数增长重试事件,如1秒,2秒,4秒,8秒等。默认次数设为5次下面是实现逻辑。
//也采用封装一个递归函数来递归调用的方法。
private static void connect(Bootstrap bootstrap,String host,int port,int retry){bootstrap.connect(host,  port).addListener(future ->{if(future.isSuccess()){System.out.println("连接成功!");}else if(retry  ==  0) {System.err.println("重试次数已用完,放弃连接!");}else{//  第几次重连int  order  =  (MAX_RETRY  -  retry)  +  1;//  本次重连的间隔int  delay  =  1  <<  order;System.err.println(newDate()  +  ":连接失败,第"  +  order  +  "次重连……");bootstrap.config().group().schedule(()  ->  connect(bootstrap,  host,  port,retry--),  delay,  TimeUnit.SECONDS);}});
} 

上面代码比较好懂,
不过这里等待一定时间后执行任务的操作,即定时任务操作,用了bootstrap.config().group().schedule()来做。
group()返回我们配置的workerGroupschedule()正是其中的方法,来定时执行一个任务。
在上面最后的else中,根据剩余重试次数retry,来确定本次重试之前要等多长时间,即delay,再通过schedule()递归调用函数本身,不过递归函数的参数retry要减1,因为它代表剩余重试次数。

其他方法

ServerBootstrap一样,Bootstrap也有attr方法来给Channel设置键值对。不再赘述。
也有option方法来设置TCP参数。
书中给了如下参数

.option(ChannelOption.CONNECT_TIMEOUT_MILLIS,  5000)
.option(ChannelOption.SO_KEEPALIVE,  true)
.option(ChannelOption.TCP_NODELAY,  true)

ChannelOption.CONNECT_TIMEOUT_MILLIS表示连接的超时时间,超过这个时间,如果仍未连接到服务端,则表示连接失败。
ChannelOption.SO_KEEPALIVE表示是否开启TCP底层心跳机制,true表示开启。
ChannelOption.TCP_NODELAY表示是否开始Nagle算法,true表示关闭,false表示开启。通俗地说,如果要求高实时性,有数据发送时就马上发送,就设置为true;如果需要减少发送次数,减少网络交互,就设置为false

结语

本文内容均来自《跟着闪电侠学Netty》。
看了看书,感觉挺有帮助的。技术还是视频,书籍,源码,实践相辅相成好。

本篇仅是对ServerBootstrapBootstrap的补充说明,后续还会按视频课程的编排来写。中间穿插一些书中写到但是视频没有提到的东西。

下篇就是开头说要写的PromiseFuture了。篇幅应该不长,只写一点。
按顺序再后面应该是handlerpipeline,还有ByteBuf

这里稍微说下,这本书里的内容其实和课程中很多部分都是重复的,毕竟说的都是Netty吗。
然后我对比了一下二者的基础部分,书接下来讲的通信协议编解码,PipelineChannelHandler,粘包拆包,双向通信。实现一个简单群聊。这些视频同样讲到了。可能有几个章节是二者独有的。二者可以对比学习。效果应该会更好吧。

后面写我尽量结合两边来写。

感谢阅读,欢迎批评指正。

相关文章:

netty入门-5 ServerBootstrap与Bootstarp

前言 本来这篇应该紧接着说明Future和Promise。 但是考虑前文第三篇即用到了ServerBootstrap来启动一个服务器&#xff0c;并且我读的闪电侠netty&#xff0c;先写的服务器与客户端启动这部分。索性就先写出来了。主要内容来自闪电侠netty ServerBootstrap ServerBootstrap就…...

JavaEE - Spring Boot 简介

1.Maven 1.1 什么是Maven 翻译过来就是: Maven是⼀个项⽬管理⼯具。基于POM(Project Object Model,项⽬对象模型)的概念&#xff0c;Maven可以通 过⼀⼩段描述信息来管理项⽬的构建&#xff0c;报告和⽂档的项⽬管理⼯具软件。 可以理解为&#xff1a;Maven是一个项目管理工具…...

SwiftUI革新:Xcode UI开发的新纪元

SwiftUI革新&#xff1a;Xcode UI开发的新纪元 SwiftUI作为Apple推出的声明式UI框架&#xff0c;彻底改变了在Xcode中构建用户界面的方式。它不仅简化了代码&#xff0c;还提高了开发效率&#xff0c;并且使得UI设计更加直观和灵活。本文将深入探讨如何在Xcode中使用SwiftUI进…...

22、基于共享内存的数据结构——用十个块来提高并发性

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 为了提高并发性&#xff0c;把…...

【ffmpeg命令入门】实现画中画

文章目录 前言画中画是什么画中画的外观描述效果展示为什么要用画中画应用场景示例 使用FFmpeg添加画中画示例命令参数解释调整嵌入视频的位置调整嵌入视频的大小处理音频 总结 前言 FFmpeg 是一款强大的多媒体处理工具&#xff0c;广泛用于音视频的录制、转换和流处理。它不仅…...

基于 LangChain+LangGraph 来实现一个翻译项目

相信大家在看文档的时候&#xff0c;有时会比较苦恼&#xff0c;比如 AI 相关的文档都是外文&#xff0c;中文文档比较少&#xff0c;看起来会比较吃力&#xff0c;有的时候会看不懂&#xff0c;翻译软件又翻得很乱&#xff0c;完全看不了&#xff0c;今天就基于 LangChain 和 …...

javascript 如何将 json 格式数组转为 excel 表格| sheetJS

案例 // https://unpkg.com/xlsx0.18.5/dist/xlsx.full.min.js function exportXlsx(jsonData, fileName , mine null) {const workbook XLSX.utils.book_new();// 将JSON数组转换成工作表const worksheet XLSX.utils.json_to_sheet(jsonData);// 向工作簿添加工作表XLSX.…...

网页制作技术在未来会如何影响人们的生活?

网页制作技术在未来会如何影响人们的生活&#xff1f; 李升伟 网页制作技术在未来可能会从以下几个方面显著影响人们的生活&#xff1a; 1. 工作与学习方式的变革&#xff1a;远程办公和在线教育将更加普及和高效。通过精心制作的网页&#xff0c;人们能够实现更便捷的协作…...

【计算机网络】网络层——IPv4地址(个人笔记)

学习日期&#xff1a;2024.7.24 内容摘要&#xff1a;IPv4地址&#xff0c;分类编址&#xff0c;子网&#xff0c;无分类编址 IPv4地址概述 在TCP/IP体系中&#xff0c;IP地址是一个最基本的概念&#xff0c;IPv4地址就是给因特网上的每一台主机的每一个接口分配一个在全世界…...

c++ 学习笔记之多线程:线程锁,条件变量,唤醒指定线程

基于CAS线程加锁方式 CAS&#xff08;Compare-And-Swap&#xff09;和 mutex 都是用于实现线程安全的技术&#xff0c;但它们适用于不同的场景&#xff0c;具有不同的性能和复杂性。下面是对两者的区别和使用场景的详细解释&#xff1a; CAS&#xff08;Compare-And-Swap&…...

《0基础》学习Python——第二十三讲__网络爬虫/<6>爬取哔哩哔哩视频

一、在B站上爬取一段视频&#xff08;B站视频有音频和视频两个部分&#xff09; 1、获取URL 注意&#xff1a;很多平台都有反爬取的机制&#xff0c;B站也不例外 首先按下F12找到第一条复制URL 2、UA伪装&#xff0c;下列图片中&#xff08;注意代码书写格式&#xff09; 3、Co…...

第13周 简历职位功能开发与Zookeeper实战

第13周 简历职位功能开发与Zookeeper实战 本章概述1. Mysql8窗口函数over使用1.1 演示表结构与数据1.2 案例1:获取男女总分数1.3 案例2****************************************************************************************本章概述 1. Mysql8窗口函数over使用 参考案例…...

什么是大型语言模型 (LLM)

本章探讨下&#xff0c;人工智能如何彻底改变我们理解和与语言互动的方式 大型语言模型 (LLM) 代表了人工智能的突破&#xff0c;它采用具有广泛参数的神经网络技术进行高级语言处理。 本文探讨了 LLM 的演变、架构、应用和挑战&#xff0c;重点关注其在自然语言处理 (NLP) 领…...

【人工智能】AI时代:探索个人潜能的新视角

文章目录 &#x1f34a;Al时代的个人发展1 AI的高速发展意味着什么1.1 生产力大幅提升1.2 生产关系的改变1.3 产品范式1.4 产业革命1.5 Al的局限性1.5.1局限一:大模型的幻觉1.5.2 局限二&#xff1a;Token 2 个体如何应对这种改变?2.1 职场人2.2 K12家长2.3 大学生2.4 创业者 …...

pyaudio VAD通过声音音频值分贝大小检测没人说话自动停止录制

效果可能说话声音小可能不被监听到,需要更改QUIET_DB阈值,另外delay_time值是低于阈值多久就可以停止保存当前的语音 import pyaudio import waveimport sys import numpy as npdef record_auto(MIC_INDEX=1):开启麦克风录音,保存至temp/speech_record.wav音频文件音量超过…...

《后端程序猿 · @Value 注释说明》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…...

【LeetCode】71.简化路径

1. 题目 2. 分析 3. 代码 我写了一版很复杂的代码&#xff1a; class Solution:def simplifyPath(self, path: str) -> str:operator [] # 操作符的栈dir_name [] # 文件名的栈idx 0cur_dir_name ""while(idx < len(path)):if path[idx] /:operator.ap…...

DockerCompose 安装环境

1. Redis version: 3 services:redis:image: redis:6.2.12container_name: redisports:- "6379:6379"environment:TZ: Asia/Shanghaivolumes:# 本地数据目录要先执行 chmod 777 /usr/local/docker/redis/data 赋予读写权限&#xff0c;否则将无法写入数据- /usr/loc…...

学习笔记之JAVA篇(0724)

p 方法 方法声明格式&#xff1a; [修饰符1 修饰符2 ...] 返回值类型 方法名&#xff08;形式参数列表&#xff09;{ java语句;......; } 方法调用方式 普通方法对象.方法名&#xff08;实参列表&#xff09;静态方法类名.方法名&#xff08;实参列表&#xff09; 方法的详…...

【Android】广播机制

【Android】广播机制 前言 广播机制是Android中一种非常重要的通信机制&#xff0c;用于在应用程序之间或应用程序的不同组件之间传递信息。广播可以是系统广播&#xff0c;也可以是自定义广播。广播机制主要包括标准广播和有序广播两种类型。 简介 在Android中&#xff0c…...

KubeSphere 容器平台高可用:环境搭建与可视化操作指南

Linux_k8s篇 欢迎来到Linux的世界&#xff0c;看笔记好好学多敲多打&#xff0c;每个人都是大神&#xff01; 题目&#xff1a;KubeSphere 容器平台高可用&#xff1a;环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇&#xff0c;在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下&#xff1a; 【Note】&#xff1a;如果你已经完成安装等操作&#xff0c;可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作&#xff0c;重…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战

前言 现在我们有个如下的需求&#xff0c;设计一个邮件发奖的小系统&#xff0c; 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其…...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

Python:操作 Excel 折叠

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

Ascend NPU上适配Step-Audio模型

1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统&#xff0c;支持多语言对话&#xff08;如 中文&#xff0c;英文&#xff0c;日语&#xff09;&#xff0c;语音情感&#xff08;如 开心&#xff0c;悲伤&#xff09;&#x…...

省略号和可变参数模板

本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...

永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器

一、原理介绍 传统滑模观测器采用如下结构&#xff1a; 传统SMO中LPF会带来相位延迟和幅值衰减&#xff0c;并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF)&#xff0c;可以去除高次谐波&#xff0c;并且不用相位补偿就可以获得一个误差较小的转子位…...

区块链技术概述

区块链技术是一种去中心化、分布式账本技术&#xff0c;通过密码学、共识机制和智能合约等核心组件&#xff0c;实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点&#xff1a;数据存储在网络中的多个节点&#xff08;计算机&#xff09;&#xff0c;而非…...