1,java网络基础
计算机网络体系结构
OSI 七层模型
1,物理层 : 物理层并不是物理媒体本身,他只是开放系统中利用物理媒体实现物理连接的功能描述和执行连接的规范;
DTE , DCE(物理光猫)
2,数据链路层 :数据链路的建立,拆除,对数据的检错,纠错是数据链路层的基本任务;
可以理解为数据通道,我们每一次网络的时候就需要 ''拨号和电信连接''
3,网络层: 路由选择和中继,在一条数据链路上复用多余网络连接;
4,传输层 :定义传输数据的协议端口号,以及流控个差错校验。
5,会话层:建立,管理,终止回话;
6,表示层:把应用提供的信息变换为能够共同理解的形式;
7,应用层 : 网络服务与最终用户的一个接口
什么是OSI?
如果你遵循了OSI的参考模型,或者相关协议的话,就能够实现互连,这就是OSI最大的一个意义
TCP /IP 协议
Transmission Control Protocol/Internet Protocol的简写,中译名为传输控制协议/因特网互联协议,是Internet最基本的协议、Internet国际互联网络的基础,由网络层的IP协议和传输层的TCP协议组成。协议采用了4层的层级结构。然而在很多情况下,它是利用 IP 进行通信时所必须用到的协议群的统称。
TCP 只有四层 ,
TCP 和 UDP
TCP 是面向连接的、可靠的流协议,通过三次握手建立连接,通讯完成时要拆除连接。 UDP是面向无连接的通讯协议,UDP通讯时不需要接收方确认,属于不可靠的传输,可能会出现丢包现象
udp主要面向查询-应答,NTP / DNS 广播通讯,
三次握手和四次挥手
TCP/IP中的数据包
TCP 中通过序列号与确认应答提高可靠性
HTTP请求的传输过程
一次完整http请求的7个过程
-
建立 TCP 连接(之前可能还有一次DNS域名解析)
-
客户端向服务器发送请求命令
-
客户端发送请求头信息
-
服务服务器应答器
-
返回响应头信息
-
服务器向客户端发送数据
-
服务器关闭 TCP 连接
HTTP 协议报文结构
请求报文结构
主题内容就是我们开发中看到的请求体
响应报文结构
对于应答报文会,
应答报文:
-
首先是两方通讯的一个协议版本,
-
然后是一个状态码,按照http协议的规定是有1xx-5xx 这5中协议
-
响应的首部字段
-
回车换行
-
具体的服务器给客户端应答的内容
一些常见术语
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口
Socket 其实在协议规范里面 没有Socket的说法;
Socket 是一个抽象,他是一组接口,它把复杂的TCP/IP 隐藏能赶在Socket 背后,
对于我们开发者来说,主机A和主机B要通讯,我们要通过一个Socket 来建立连接;
然后socket 就利用tcp/ip 来处理连接,也就是所,他是对TCP/IP 的一个封装,在网络开发我们只需要Socket 就可以了;
一个Socket 也就代表了一个主机上的通讯线路;
Socket 不管是在windows 和linux 都是一个网络连接;
短连接:
短链接最常见的就是http 连接,
我的socket 用完之后就断开连接了
场景:用于并发量大,但是每个用户又无需频繁操作
长连接:
我的socket 用完之后没有断开连接,保持连接;
相当于http 里面开了一个keep alive 保持存活,不管我有没有使用,你要给我保持连接;
服务器推送一般使用的是长连接,
为什么要有一个连接池,就是为了这个连接不中断,保持连接,所以连接处一般往往是长连接;
LInux网络IO模型
同步和异步,
同步和异步,这两个关注结果的通知机制;
同步就是执行完一个再执行下一个;
异步就是我不去等待他的返回结果直接执行下一步;
异步就是一个回调;
阻塞和非阻塞:
关注的是调用方会不会等待结果返回;
如果方法没有返回就一直等着就是阻塞;
如果调用方不用等待调用结果返回,继续做相关的事情叫非阻塞;
*1.同步阻塞:*
同步阻塞基本也是编程中最常见的模型,打个比方你去商店买衣服,你去了之后发现衣服卖完了,那你就在店里面一直等,期间不做任何事(包括看手机),等着商家进货,直到有货为止,这个效率很低。
*2.同步非阻塞:* 同步非阻塞在编程中可以抽象为一个轮询模式,你去了商店之后,发现衣服卖完了,这个时候不需要傻傻的等着,你可以去其他地方比如奶茶店,买杯水,但是你还是需要时不时的去商店问老板新衣服到了吗。
*3.异步阻塞:* 异步阻塞这个编程里面用的较少,有点类似你写了个线程池,submit然后马上future.get(),这样线程其实还是挂起的。有点像你去商店买衣服,这个时候发现衣服没有了,这个时候你就给老板留给电话,说衣服到了就给我打电话,然后你就守着这个电话,一直等着他响什么事也不做。这样感觉的确有点傻,所以这个模式用得比较少。
*4.异步非阻塞:* 好比你去商店买衣服,衣服没了,你只需要给老板说这是我的电话,衣服到了就打。然后你就随心所欲的去玩,也不用操心衣服什么时候到,衣服一到,电话一响就可以去买衣服了。
Linux下的五种I/O 模型:
1,阻塞I/O(blocking I/O)
在编程当中用的最多的是阻塞IO, 因为客户端不需要去服务很多的socket通讯,在编程上面阻塞IO也会相对的简单;
2,非阻塞I/O (nonblocking I/O)
3,I/O复用(select 、poll和epoll) (I/O multiplexing)
对于服务器端来说用的最多的是 IO复用
4,信号驱动I/O (signal driven I/O (SIGIO))
5,异步I/O (asynchronous I/O )
异步IO 是未来的一个趋势,在linux 没有真正的使用异步IO
只有windows 才是真正的使用了异步IO, 称IOCP
阻塞I/O
在linux里面调用一个函数 这个应用程序会在recvfrom 一直等待,等到内核把数据准备好;
网卡数据需要操作系统读取到内核空间, 应用程序需要用了,在从内核中传给应用程序;
当应用程序调用recvfrom 这个IO的时候,这个应用程序会一直等待,知道内核空间的数据拷贝到用户空间之后recvfrom 才会返回;
非阻塞IO模型
当我应用程序想recvfrom发起调用的时候,他会向内核发起调用,内核会传递一个信息,传递信息给应用程序,应用程序会知道没有数据到来,这个时候回发起第二次调用,内核会告诉他没有没有,直到内核有数据,这个时候就会被阻塞了,阻塞到数据从内核拷贝到用户空间之后,recvfrom方法才会返回;
区别只有数据在拷贝的时候才会被阻塞
,在实际编程当中也很少用非阻塞IO,因为不断重试非常的消耗CPU
IO复用模型
在大多数情况下使用最多的一个模型,也就是JDK中所谓的NIO
对于某一次通讯而言,他还是阻塞的,但是他可以服务于多个网络通讯;
对于linux 服务器而言,我么可以服务多个通讯;
IO复用有一个select 函数, 调用的时候会问内核要数据,没有数据的时候就阻塞,但是会有多个socket 不断的做一个select函数调用,当有哪个select 返回了之后就进行哪个select的一个recvfrom 调用;
多个select会挂在内核上,没有数据的select 内核不会再去调用检查;
poll 和epoll 早期的时候是
信号驱动IO
对于信号驱动也很少用,就是一个信号通知的作用,在应用程序调用的时候迅速发送一个通知的信号;
异步IO模型
整个调用过程都是非阻塞的, 等到 数据全部同步之后,通知应用程序已经返回了
整个过程应用程序都不用管,都是由操作系统完成了;
5个IO模型的比较
select ,poll , epoll 的区别
select 在打开连接数上有限制;
poll ,对连接数是根据我的物理机器来决定的没有上限;
epoll 对最大连接数有上限,但是非常大;,如,1G内存可以打开10w个连接;
select 会去遍历 挂在操作系统上,
epoll 会让linux 内核与用户空间共享一个内存;
1、支持一个进程所能打开的最大连接数
select | 单个进程所能打开的最大连接数有FD_SETSIZE宏定义,其大小是32个整数的大小(在32位的机器上,大小就是3232,同理64位机器上FD_SETSIZE为3264),可以对进行修改,然后重新编译内核,但是性能可能会受到影响。 |
---|---|
poll | poll本质上和select没有区别,但是它没有最大连接数的限制,原因是它是基于链表来存储的 |
epoll | 连接数有上限,但是很大,1G内存的机器上可以打开10万左右的连接,2G内存的机器可以打开20万左右的连接 |
2、FD剧增后带来的IO效率问题
select | 因为每次调用时都会对连接进行线性遍历,所以随着FD的增加会造成遍历速度慢的“线性下降性能问题”。 |
---|---|
poll | 同上 |
epoll | 因为epoll内核中实现是根据每个fd上的callback函数来实现的,只有活跃的socket才会主动调用callback,所以在活跃socket较少的情况下,使用epoll没有前面两者的线性下降的性能问题,但是所有socket都很活跃的情况下,可能会有性能问题。 |
3、 消息传递方式
select | 内核需要将消息传递到用户空间,都需要内核拷贝动作 |
---|---|
poll | 同上 |
epoll | epoll通过内核和用户空间共享一块内存来实现的。 |
小结:同步和异步关注的是那结果, 阻塞和非阻塞关注的是这个线程,阻塞是当前线程挂起不能做其他事情,非阻塞当前线程不会挂起,可以去做其他事情;