网络编程(一)网络编程基础
OSI 七层模型
层数 | 名称 | 作用 |
---|---|---|
7 | 应用层 | 网络服务与最终用户的一个接口 |
6 | 表示层 | 把应用层提供的信息变换为能够共同理解的形式 |
5 | 会话层 | 建立、管理、终止会话。 |
4 | 传输层 | 定义传输数据的协议端口号,以及流控和差错校验 |
3 | 网络层 | 路由选择和中继,在一条数据链路上复用多条网络连接 |
2 | 数据链路层 | 数据链路的建立,拆除,对数据的检错,纠错是数据链路层的基本任务。 |
1 | 物理层 | 物理层并不是物理媒体本身,它只是开放系统中利用物理媒体实现物理连接的功能,描述和执行连接的程序 |
TCP/IP 协议
OSI 七层模型 | TCP/IP 概念层模型 | 功能 | TCP/IP 协议族 |
---|---|---|---|
应用层 | 应用层 | 文件传输,电子邮件,文件服务,虚拟终端 | tftp、http、snmp、ftp、smtp、dns、telnet |
表示层 | 应用层 | 数据格式化,代码转换,数据加密 | 没有协议 |
会话层 | 应用层 | 解除或建立与别的节点的联系 | 没有协议 |
传输层 | 传输层 | 提供端对端的接口 | tcp、udp |
网络层 | 网络层 | 为数据包选择路由 | ip、icmp、rip、ospf、bcp、icmp |
数据链路层 | 链路层 | 传输有地址的帧以及错误检测功能 | slip、cslip、ppp、arp、rarp、mtu |
物理层 | 链路层 | 以二进制数据形式在物理媒体上传输数据 | iso2110、ieee802、ieee802.2 |
数据传输过程
IP 包结构是这样的:
TCP 的包结构:
基于 TCP 和 UDP 的数据封装及解析示例如下:
TCP 和 UDP
TCP
TCP 是面向连接的、可靠的流协议,通过三次握手建立连接,通讯完成时要拆除连接。
三次握手
- B 的 TCP 服务器进程先创建传输控制块 TCB,准备接受客户进程的连接请求。然后服务器进程就处于 LISTEN(收听)状态,等待客户的连接请求。若有,则作出响应。
- 1)第一次握手:A 的 TCP 客户进程也是首先创建传输控制块 TCB,然后向 B 发出连接请求报文段,(首部的同步位 SYN=1**,初始序号 seq=x),(SYN=1 的报文段不能携带数据)但要消耗掉一个序号,此时 TCP 客户进程进入 SYN-SENT(同步已发送)状态。
- 2)第二次握手:**B 收到连接请求报文段后,如同意建立连接,则向 A 发送确认,在确认报文段中(SYN=1,ACK=1,确认号 ack=x+1,初始序号 seq=y),测试 TCP 服务器进程进入 SYN-RCVD(同步收到)状态;
- 3)第三次握手:**TCP 客户进程收到 B 的确认后,要向 B 给出确认报文段(ACK=1,确认号 ack=y+1,序号 seq=x+1)(初始为 seq=x,第二个报文段所以要 +1),ACK 报文段可以携带数据,不携带数据则不消耗序号。TCP 连接已经建立,A 进入 ESTABLISHED(已建立连接)。
- 当 B 收到 A 的确认后,也进入 ESTABLISHED 状态。
总结三次握手过程:
- 第一次握手:起初两端都处于 CLOSED 关闭状态,Client 将标志位 SYN 置为 1,随机产生一个值 seq=x,并将该数据包发送给 Server,Client 进入 SYN-SENT 状态,等待 Server 确认;
- 第二次握手:Server 收到数据包后由标志位 SYN=1 得知 Client 请求建立连接,Server 将标志位 SYN 和 ACK 都置为 1,ack=x+1,随机产生一个值 seq=y,并将该数据包发送给 Client 以确认连接请求,Server 进入 SYN-RCVD 状态,此时操作系统为该 TCP 连接分配 TCP 缓存和变量;
- 第三次握手:Client 收到确认后,检查 ack 是否为 x+1,ACK 是否为 1,如果正确则将标志位 ACK 置为 1,ack=y+1,并且此时操作系统为该 TCP 连接分配 TCP 缓存和变量,并将该数据包发送给 Server,Server 检查 ack 是否为 y+1,ACK 是否为 1,如果正确则连接建立成功,Client 和 Server 进入 ESTABLISHED 状态,完成三次握手,随后 Client 和 Server 就可以开始传输数据。
四次挥手
- 1)A 的应用进程先向其 TCP 发出连接释放报文段(FIN=1,序号 seq=u),并停止再发送数据,主动关闭 TCP 连接,进入 FIN-WAIT-1(终止等待 1)状态,等待 B 的确认。
- 2)B 收到连接释放报文段后即发出确认报文段,(ACK=1,确认号 ack=u+1,序号 seq=v),B 进入 CLOSE-WAIT(关闭等待)状态,此时的 TCP 处于半关闭状态,A 到 B 的连接释放。
- 3)A 收到 B 的确认后,进入 FIN-WAIT-2(终止等待 2)状态,等待 B 发出的连接释放报文段。
- 4)B 没有要向 A 发出的数据,B 发出连接释放报文段(**FIN=1,ACK=1,序号 seq=w,确认号 ack=u+1),**B 进入 LAST-ACK(最后确认)状态,等待 A 的确认。
- 5)A 收到 B 的连接释放报文段后,对此发出确认报文段(ACK=1,seq=u+1,ack=w+1),A 进入 TIME-WAIT(时间等待)状态。此时 TCP 未释放掉,需要经过时间等待计时器设置的时间 2MSL 后,A 才进入 CLOSED 状态。
总结四次挥手过程:
起初 A 和 B 处于ESTABLISHED 状态——A 发出连接释放报文段并处于FIN-WAIT-1 状态——B 发出确认报文段且进入CLOSE-WAIT 状态——A 收到确认后,进入FIN-WAIT-2 状态,等待 B 的连接释放报文段——B 没有要向 A 发出的数据,B 发出连接释放报文段且进入LAST-ACK 状态——A 发出确认报文段且进入TIME-WAIT 状态——B 收到确认报文段后进入CLOSED 状态——A 经过等待计时器时间 2MSL 后,进入CLOSED 状态。
UDP
UDP 是面向无连接的通讯协议,UDP 通讯时不需要接收方确认,属于不可靠的传输,可能会出现丢包现象。
TCP 与 UDP 对比
TCP | UDP |
---|---|
通信双方需要建立并维持连接,占用一定的系统资源 | 通信双方不需要建立连接,占用的系资源少 |
传输数据可靠,丢包很少发生 | 传输数据不可靠,丢包属于正常现象,丢包时会重传 |
与 TCP 相比,传输效率高,通讯速度快 | |
对传输质量要求较高时使用 TCP 协议 | 对传输质量要求不高,要求传输速度更快时使用 UDP 协议 |
端口号
端口号用来识别同一台计算机中进行通信的不同应用程序,因此,它也被称为程序地址。
Socket
Socket 是应用层与 TCP/IP 协议族通信的中间软件抽象层,它是一组接口。
JAVA 中实现通信的 IO 主要是:同步阻塞 IO(BIO)、同步非阻塞 IO(NIO)、异步非阻塞 IO(AIO)。
同步和异步,阻塞和非阻塞
同步和异步关注结果是否立即返回;
阻塞和非阻塞关注调用方是否等待结果返回。
linux 下的五种 I/O 模型
(1) 阻塞 I/O (Blocking I/O)
从上图可以看到在整个过程中,当用户进程进行系统调用时,内核就开始了 I/O 的第一个阶段,准备数据到缓冲区中,当数据都准备完成后,则将数据从内核缓冲区中拷贝到用户进程的内存中,这时用户进程才解除 block 的状态重新运行。
所以,Blocking I/O 的特点就是在 I/O 执行的两个阶段都被 block 了。
(2) 非阻塞 I/O (Non-Blocking I/O)
从上图可以看到在 I/O 执行的两个阶段中,用户进程只有在第二个阶段被阻塞了,而第一个阶段没有阻塞,但是在第一个阶段中,用户进程需要盲等,不停的去轮询内核,看数据是否准备好了,因此该模型是比较消耗 CPU 的。
(3) I/O 复用(I/O Multiplexing)
从上图可以看到在 I/O 复用模型中,I/O 执行的两个阶段都是用户进程都是阻塞的,但是两个阶段是独立的,在一次完整的 I/O 操作中,该用户进程是发起了两次系统调用。
(4) 信号驱动的 I/O (Signal Driven I/O)
该模型也叫作基于事件驱动的 I/O 模型,可以看到该模型中,只有在 I/O 执行的第二阶段阻塞了用户进程,而在第一阶段是没有阻塞的。
乍看起来感觉和非阻塞模型很相似,其实不同之处就在于,该模型在 I/O 执行的第一阶段,当数据准备完成之后,会主动的通知用户进程数据已经准备完成,即对用户进程做一个回调。该通知分为两种,一为水平触发,即如果用户进程不响应则会一直发送通知,二为边缘触发,即只通知一次。
(5) 异步 I/O (Asynchrnous I/O)
在该模型中,当用户进程发起系统调用后,立刻就可以开始去做其它的事情,然后直到 I/O 执行的两个阶段都完成之后,内核会给用户进程发送通知,告诉用户进程操作已经完成了。