开发进阶系列:Java网络通信编程从基础到框架
- IO(BIO)和NIO的区别:其本质就是阻塞和非阻塞的区别。
- NIO基于Buffer(缓冲区)、Channel(管道)、Selector(选择器)。
简单说,就是selector会不断地轮询注册在其上的通道(channel),如果某个通道发生了读写操作,这个通道就处于就绪状态,会被selector轮询出来,然后通过selectionKey可以取得就绪的channel集合,从而进行后续的IO操作。
一个多路复用器(selector)可以负责成千上万channel通道,没有上限,这也是JDK使用了epoll代替了传统的select实现,获取连接句柄没有限制。这也就意味着我们只要一个线程负责selector的轮询,就可以接入成千上万个客户端,这就是JDK NIO库的巨大进步。
(扩展——Epoll是什么:epoll是Linux内核为处理大批量文件描述符而作了改进的poll,是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。另一点原因就是获取事件的时候,它无须遍历整个被侦听的描述符集,只要遍历那些被内核IO事件异步唤醒而加入Ready队列的描述符集合就行了。epoll除了提供select/poll那种IO事件的水平触发(Level Triggered)外,还提供了边缘触发(Edge Triggered),这就使得用户空间程序有可能缓存IO状态,减少epoll_wait/epoll_pwait的调用,提高应用程序效率。)
selector线程就类似一个管理者(master),管理成千上万个管道,然后轮询哪个管道的数据已经准备好,通知cpu执行IO的读取或写入操作。
selector模式:当IO事件(管道)注册到选择器以后,selector会分配给每个管道一个key值,相当于标签。selector选择器是以轮询的方式进行查找注册的所有IO事件(管道),当我们的IO事件(管道)准备就绪后,select就会识别,会通过key值来找到相应的管道,进行相关的数据处理操作(从管道里读或写数据,写到我们的数据缓冲区中)。
每个管道都会对选择器进行注册不同的事件状态,以便选择器查找。
SelectionKey.OP_CONNECT SelectionKey.OP_ACCEPT SelectionKey.OP_READ SelectionKey.OP_WRITE
面试常问:Bio——NIO——AIO区别和进化过程
熟悉tcp编程的可能都知道,无论是服务器端还是客户端,当我们读取或者发送数据的时候,都需要考虑tcp底层的粘包/拆包机制。
tcp是一个“流”协议,所谓流就是没有界限的一串数据。大家可以想象下如果河里的水就好比数据,他们是连成一片的,没有分界线。tcp底层并不了解上层的业务数据具体的含义,它会根据tcp缓冲区的实际情况进行包的划分,也就是说,在业务上,我们一个完整的包可能会被tcp分成多个包进行发送,也可能把多个小包封装成一个大的数据包发送出去,这就是所谓的tcp粘包、拆包问题。
分析tcp粘包、拆包问题的产生原因:
1.应用程序write写入的字节大小大于套接口发送缓冲区的大小
2.进行MSS大小的TCP分段
3.以太网帧的payload大于MTU进行IP分片
拆包的三种解决方案:
1.消息定长,例如每个报文的大小固定为200个字节,如果不够,空位补空格。
2.在包尾部增加特殊字符进行分割,例如加回车等。
3.将消息分为消息头和消息体,在消息头中包含表示消息总长度的字段,然后进行业务逻辑的处理
拆包具体实现可以用两个类:
1.分隔符类:DelimiterBasedFrameDecoder(自定义分隔符)
2.FixedLengthFrameDecoder(定长)
2、Netty编解码技术
编解码技术,说白了就是Java序列化技术,序列化目的就两个,第一是进行网络传输,第二是对象持久化。
虽然我们可以使用Java进行对象序列化,netty去传输,但是Java序列化的硬伤太多,比如Java序列化没法跨语言、序列化后码流太大、序列化性能太低等等
主流的编解码框架:
JBoss的Marshalling包(是一个Java对象序列化包,对JDK默认的序列化框架进行了优化,又保持了跟java.io.serializable接口的兼容,同时增加了一些可调参数,与netty结合后进行序列化对象的代码编写很简单)
google的protobuf
基于protobuf的Kyro
MessagePack框架
3、Netty主要应用场景
1.数据通信
两台及以上机器如何使用netty通信:
1.使用长连接通道不断开的形式进行通信,也就是服务器和客户端的通道一直处于开启状态,如果服务器性能够好,并且客户端数量也比较少的情况下,推荐此方式。
2.一次性批量提交数据,采用短连接方式。也就是我们会把数据保存在本地临时缓冲区或者临时表里,当达到临界值时进行一次性批量提交,又或者根据定时任务轮询提交,这种情况的弊端是做不到实时传输,对实时性要求不高的应用程序中可以推荐使用。
3.我们可以使用一种特殊的长连接,在指定某一段时间之内,服务器与某台客户端没有任何通信,则断开连接。下次连接则是客户端向服务器发送请求的时候,再次建立连接。这种模式需要考虑两个因素,
3.1如何在超时(即服务器和客户端没有任何通信)后关闭通道,关闭后又该如何再次建立连接
3.2客户端宕机时,我们不用管,下次客户端重启之后我们就可以与服务器建立连接,但当服务器宕机时,我们的客户端如何与服务器进行连接
2.心跳测试
我们使用socket通信一般会经常处理多个服务器之间的心跳检测,一般服务器集群,会有一台或多台主机(master),和多台从机(slave),那么主机肯定要时时刻刻知道自己下面的从机的各方面情况,然后进行实时监控的功能,这个在分布式架构里叫做心跳检测或心跳监控。最佳处理方案还是使用一些通信框架进行实现,如netty。
3.文件上传下载
附:Mina是一个和netty类似的框架,它属于Apache。
开发进阶系列:Java网络通信编程从基础到框架的更多相关文章
- 【Xamarin开发 Android 系列 7】 Android 结构基础(下)
原文:[Xamarin开发 Android 系列 7] Android 结构基础(下) *******前期我们不打算进行太深入的东西,省的吓跑刚进门的,感觉门槛高,so,我们一开始就是跑马灯一样,向前 ...
- 【TCP/IP】之Java socket编程API基础
Socket是Java网络编程的基础,深入学习socket对于了解tcp/ip网络通信协议很有帮助, 此文讲解Socket的基础编程.Socket用法:①.主要用在进程间,网络间通信. 文章目录如下: ...
- Java程序员从笨鸟到菜鸟之(十三)java网络通信编程
本文来自:曹胜欢博客专栏.转载请注明出处:http://blog.csdn.net/csh624366188 首先声明一下,刚开始学习java网络通信编程就对他有一种畏惧感,因为自己对网络一窍不通,所 ...
- 【Xamarin开发 Android 系列 6】 Android 结构基础(上)
原文:[Xamarin开发 Android 系列 6] Android 结构基础(上) 前面大家已经熟悉了什么是Android,而且在 [Xamarin开发 Android 系列 4] Android ...
- java并发编程 线程基础
java并发编程 线程基础 1. java中的多线程 java是天生多线程的,可以通过启动一个main方法,查看main方法启动的同时有多少线程同时启动 public class OnlyMain { ...
- 推荐扔物线的HenCoder Android 开发进阶系列 后期接着更新
官网地址:http://hencoder.com/ 我来做一次辛勤的搬运工 HenCoder:给高级 Android 工程师的进阶手册 HenCoder Android 开发进阶: 自定义 View ...
- Java并发编程核心方法与框架-CountDownLatch的使用
Java多线程编程中经常会碰到这样一种场景:某个线程需要等待一个或多个线程操作结束(或达到某种状态)才开始执行.比如裁判员需要等待运动员准备好后才发送开始指令,运动员要等裁判员发送开始指令后才开始比赛 ...
- java网络通信编程
网络编程就是在两个或两个以上的设备(例如计算机)之间传输数据.程序员所作的事情就是把数据发送到指定的位置,或者接收到指定的数据,这个就是狭义的网络编程范畴.在发送和接收数据时,大部分的程序设计语言都设 ...
- Java Socket编程----网络基础
详见:https://www.cnblogs.com/rocomp/p/4790340.html Java最初是作为网络编程语言出现的,其对网络提供了高度的支持,使得客户端和服务器的沟通变成了现实,而 ...
- Java 并发编程实践基础 读书笔记: 第二章 构建线程安全应用程序
1,什么是线程安全性? 简单概括就是一个类在多线程情况下能安全调用就是线程安全 2,Servlet 的线程安全性 默认是非线程安全的,写servlet代码的时候需要注意线程安全,注意同步 3,vo ...
随机推荐
- NC23413 小A买彩票
题目链接 题目 题目描述 小A最近开始沉迷买彩票,并且希望能够通过买彩票发家致富.已知购买一张彩票需要3元,而彩票中奖的金额分别为1,2,3,4元,并且比较独特的是这个彩票中奖的各种金额都是等可能的. ...
- logging --- Python 的日志记录工具
logging --- Python 的日志记录工具 源代码: Lib/logging/__init__.py Important 此页面仅包含 API 参考信息.教程信息和更多高级用法的讨论,请参阅 ...
- od命令
od命令 od命令会读取所指定的文件的内容,并将其内容以八进制字节码呈现出来. 语法 od [OPTION]... [FILE]... od [-abcdfilosx]... [FILE] [[+]O ...
- nginx配置反向代理缓存
说明 最近运维一个网站里面含有不经常变化的小图片,而每次请求都需要调用file接口获取不太合适.所以就想利用nginx的反向代理缓存来减轻服务接口的请求压力. 工作原理 Nginx反向代理缓存,当客户 ...
- Linux中作业控制命令
开门见山,最近.NET劝退师要在linux上写些长时间运行的脚本,获取Azure BlobStorage存储的数据. 记录一下Linux中后台执行作业的命令. Linux作业 作业(Job)是shel ...
- 2021-07-20 value!==value,JavaScript中NaN
关于NaN NaN 属性代表一个"不是数字"的number类型的字面量值.这个特殊的值是因为运算不能执行而导致的,不能执行的原因要么是因为其中的运算对象之一非数字. NaN的出现场 ...
- AI数字人SadTalker实战
1.概述 AI数字人在营销和品牌推广中扮演着至关重要的角色,许多企业和个人正积极利用数字技术来打造属于自己的财富.有没有一种简单而免费的方式来创建自己的数字人呢?本篇博客笔者将为大家介绍如何搭建属于自 ...
- FFmpeg开发笔记(七):ffmpeg解码音频保存为PCM并使用软件播放
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...
- Unity3D常用方法
1.StartCoroutine(Thread1()) 启动协程运行Thread1()方法. 注意是协程,不是线程,详情见:https://www.jianshu.com/p/6d923cb0c900 ...
- 【Azure 应用服务】应用服务连接 Azure MySQL 一直失败,报错 Create connection error
问题描述 App Service上部署的Java应用,连接 Azure Database for MySQL 失败.错误信息:Create connection error, url: jdbc:my ...