java 网络编程 方式_JAVA网络编程

概念

BIO  阻塞io,1.4之前

NIO  no-blocking io 非阻塞io,jdk1.4

AIO  异步io,jdk1.7

浏览器输入网址,敲下回车之后发生了什么?

1.URL解析

cb3f03553a158cc2175af255b7ba224a.png

2.DNS解析

概念:Domain Name System,域名系统,本质上是一个分布式数据库。将人类可读的域名解析成计算机可读的IP地址

53310c5b543032abcd7f31bbdf463a27.png

解析顺序:从右向左

38ab0f43b61738a3305987054d7ae521.png

域名的层级:类似于索引,一级一级更有效率的查找

dac5aefe9829a98f816b66edd696d35d.png

DNS查询的两种方式:递归与迭代

0e228bf9d0c2bdbd12872a1687e1202e.png

001bc3f4d9cf0b37db9912ee0f4d955c.png

网络协议

7723947a7d0daf65f394de5396c9c5eb.png

各个层的数据包格式

一个数据包叫一个帧,最大1518字节,经过每个层的时候,会加上特定的标头信息

ef136498410282bfba27e3b95ec1be53.png

java.io专业术语

49b28e34131071850b1ad91b2b5240b4.png

3f965111ade5d35204e935e501091c0c.png

45e20403be51b98ad63ae4654f415b83.png

字符流:相对高级,处理人类可以理解和阅读的字符

基本字符流:

54449610155a9ae7cb3319bdb4fb5cbc.png

高级字符流:

e85817090d4865e1d25147d46330f1b1.png

字节流:相对低级,处理字节,1字节=8bit

基本字节流:

c9598fa4eddbfff6ea963a9fca0df4c8.png

高级字节流:

f04e2271e28fb3ebbc1e74ccba6c67f2.png

设计模式:装饰者模式,高级流套在低级流之上

7d2aafbb83d90edffd54f733de95708f.png

b1b315fa3c837287f8887c5cbf994d3f.png

Socket

socket以ip+port作为唯一标识,与网卡驱动进行绑定,实现点对点的通信

unix系统中,一切皆是文件,socket也不例外,这就是为什么在多路复用模型中,总是会提到文件描述符这个词语了。

4547f043eadd676b207b22d762958e3a.png

9fea7facc8c929db6308f937b42eb499.png

ca0c3d5248416f9e46f435fb160080bb.png

同步异步阻塞非阻塞

一个表白的故事,一个男生向心仪已久的女生表白

同步:女生想了一段时间,当场给出了自己的答复

2d352946218d6cd2cfdc949bcfb01fa9.png

异步:女生说,你让我考虑几天,想好了我会打你电话

5191bb3348f6c15e066c38b884901135.png

阻塞:男生心心念念,茶不思饭不想,一心等待着女生的答复。

cb11f449f9b5580a58d3bf77c4e3b738.png

非阻塞:男生落落大方,个人生活并没有被表白这一件事情完全占据,等待回复这段时间,正常在做自己的事情,比如打打篮球

966b49baf027b3c8c7f9b292294b9aae.png

线程池

本质上为了线程复用,银行办理业务的故事

单线程:只有一个柜员,顾客排队办理业务。

多线程非线程池:有客户就招柜员,办理完了就辞退柜员,再有新的顾客再重新招聘柜员,这无疑是非常可笑的。

88eebb5a88fb990766695ca27298b7a4.png

线程池:有一批固定的柜员,平时作为常设窗口提供服务(核心线程数),

业务繁忙的时候,由HR去招聘一批员工(线程工厂),

如果窗口已经全部开放(最大线程数),客户仍然很多,就需要在大厅排队办理(工作队列),

如果业务非常火爆(比如听过银行破产,储户争相取款- -),整个大厅挤满了客户,那么对于其他大厅外的客户,银行只能说no,告知暂时无法提供服务(拒绝策略)

业务高峰过去之后,新招的员工并不会被立即辞退,只有那些长时间没有业务的员工,才会被HR辞退(空闲时间)

f3536c24c2eade4cc0fe3fe7eb48b697.png

java提供的线程池(除此之外 ,还有手动创建,ThreadpoolExecutor、ScheduledThreadpoolExecutor、Fork Join Pool):

621e6143327bdfaaf358f70848a8f991.png

cc94a61b8f7b96d7c3c40cfa1303c611.png

JAVA IO的前世:BIO阻塞模型

3598d3921c222336a3b5607cce9e1543.png

84cfcc7f0b95b6d3e2ca8bef447f51d6.png

JAVA IO的今生:NIO非阻塞模型

5b7a1c6d13979042722a88f440d6e9df.png

2e83eee84e3b11c14f91b8c35ce81ebf.png

buffer解析

channel是读写双向的,依赖buffer来实现,通过flip()方法来实现读/写模式的翻转

写模式

5dc8d6f5ea42ed45eedc6dbb7515e3b8.png

读模式,limit移动到之前写模式的最后一条,position移动到起始位置。即只能读取写模式下写入到buffer中的数据

bc3dae8fd6a540197f9fd6311326a595.png

如果数据全部读取完,调用clear()方法重新转换成写模式,limit回到最末尾,position回到起始位置

clear()方法其实并没有真的去清除buffer中的数据,只是移动了两个指针而已,但是下次再写入的时候,原有数据就会被覆盖,效果上等同于清除,是一个很巧妙而高效的方法

0eb996113d3076aea007e9502973d3f2.png

如果数据并未全部读完,在这之前需要先转换成写模式,则调用compact()方法

compact()方法把之前未读完的数据复制到buffer的最前面,然后把position指向紧跟着的那个位置,从这个位置开始写入新的数据,limit移动到末尾,这样可以确保每次读的时候是从上一次未读取完的位置开始继续读取。

10e1a4a1252bf72ffe45209d007836e1.png

channel解析

channel之间可以直接进行数据交换

3665f1c8f91b2ad663a03b2b62832d48.png

几个重要的channel

99ae3027e3b981a59171e09e3c872c3f.png

多方法实现文件拷贝

95898edaffb84715ab9525e56e00fb14.png

不带缓冲区的字节流拷贝

带缓冲区的字节流拷贝

基于channer的buffer进行拷贝

两个channel之间直接拷贝

性能对比:三个不同大小的文件,小的400K,中等的10M。大的500M,四个拷贝方法均执行5次,取平均值进行比较

不带缓冲区的字节流拷贝性能非常差,几千倍的差距

其他三种方法差别不大,随着文件的增大,nio的方法效率相对来说比传统的bufferedStream好一些

其实传统io的方法实现在新版本的jdk中已经被重写过了,在jdk1.4的时候,nio方法的性能要比传统io好很多,目前主流的jdk1.8中,底层实现差不多,所以性能没有太明显的差距了。

3d3b2689da7b9730361db51efd496aa5.png

selector解析

所有的channel注册在selector上面,由selector来监测channel的状态变化

0d45c5973b7ded4a1768c294ded768b0.png

channel的状态变化

connect:socketChannel连接到了服务器上

accept:serverSocketChannel接受了一个连接

read:channel上有数据,处于可读状态

write:channel处于可写入状态

7366cde15ddf76a21370c6e791fa6396.png

在Selector上注册channel

每个channel获得一个唯一的SelectionKey,interestOps()关心的事件,readyOps()就绪的事件

a3c98a6236b1efbc718a8b0f8c8de699.png

使用selector选择channel

select()统计所有注册的channel事件就绪的个数,操作完之后需要手动的重置就绪状态,以便当channel再次就绪的时候selector可以正确的统计

f69148779ad173edca5a939fb23bba45.png   

edf6d1e25288c9946ae385dde489b62a.png

5a54eef944ddb54acee9c7752ca7fb12.png

NIO编程模型

socketServerChannel注册监听accept事件,响应说明有新的socketChannel建立了连接,然后对这个新的socketChannel在selector上注册监听read事件,当read事件就绪的时候(buffer中有可读数据),由selector所在的线程去处理该io请求

这样,selector所在的这个线程可以同时处理多个io请求,不像BIO模型中每个io请求都需要有一个单独的线程去一对一的阻塞处理

b1cdf0d8f63016951f48c14c3506c3e1.png

JAVA IO的后世之师:AIO异步模型

内核IO模型

阻塞式I/O:每次系统调用阻塞,知道成功返回数据为止

a8657ed96cd9706ba4d138471795f46f.png

非阻塞式I/O:不停的进行系统调用,没有数据就直接返回无数据,知道有成功返回为止

57c23fdcd0275dcf7a847b3b604a21c2.png

I/O多路复用:不再由应用程序自身不停的进行系统调用,交由selector来监听事件,事件就绪的时候,会返回可读条件,然后应用程序发起系统调用,成功返回数据

99c59412347247117954026bf9ff127d.png

异步I/O:前面三种都是同步调用,无论是阻塞还是非阻塞,应用程序必须主动发起系统调用才能得到数据,在异步I/O模型中,应用程序先发起系统调用,如果此时数据没有准备好,

则返回无数据(非阻塞),当未来的某个时间,内核将数据准备好了之后,就会执行相应的回调函数

f6e7fe4239f8c30587c59af48b001635.png

异步调用机制

AIO中的异步操作

49bcd4778a27c46710122c626f891623.png

异步实现原理

基于Future,异步阻塞,用于客户端

98a21fd183732d315f78d1cb43371560.png

基于CompletionHandler,异步非阻塞,用于服务端 ,底层有一个AsyncronousChannelGroup线程池,用来执行回调函数,性能比nio的单线程同步非阻塞selector更高,AIO模型的精髓也就在这里。

572dc42b63bba376289a83b4ee4b4515.png

AIO编程模型

2498ba80a067b40f20d1bc95e2ab609e.png

三种IO模型适用情境

c0e3270ab55edada2b19f9aecfd48cbe.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值