目录
1、网络编程
1.1 OSI 网络七层模型
1.1.1 OSI 参考模型
1.1.2 网络数据传输过程
2 传输层通信协议
2.1 TCP
2.1.1 TCP的3次握手过程
2.1.2 TCP四次挥手过程
2.2 UDP
3 网络编程的IP地址
4 端口
5 套接字
1、网络编程
1.1 OSI 网络七层模型
1.1.1 OSI 参考模型
网络模型作用:进行数据封装
OSI 开放式系统互联。OSI模型把网络通信的工作分为7层,从下到上分别是物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。
OSI只是存在于概念和理论上的一种模型,它的缺点是分层太多,增加了网络工作的复杂性,所以没有大规模应用。后来人们对OSI进行了简化,合并了一些层,最终只保存了4层,从下到上分别是接口层、网络层,传输层和应用层,也就是后来的TCP/IP模型。
OSI 各层模型功能:
1-> 物理层
利用传输介质为数据链路层提供物理连接,实现比特流的透明传输。
数据单位:比特
典型设备:光纤、电缆
2-> 数据链路层
在物理层提供的比特流的基础上,通过差错控制、流量控制方法,使有差错的物理线路变为无差错的数据链路,即提供可靠的通过物理介质传输数据的方法。
数据单位:帧。
3-> 网络层
通过 IP 寻址来建立两个节点之间的连接
4-> 传输层
向用户提供可靠的端到端的差错和流量控制,保证报文的正确传输,同时向高层屏蔽下层数据通信的细节,即向用户透明地传送报文。
5-> 会话层
组织和协调两个回话进程之间的通信,并对数据交换进行管理。
6-> 表示层
表示层要完成的功能主要有不同数据编码格式的转换,提供数据压缩、解压缩服务,对数据进行加密、解密。
7-> 应用层
直接向用户提供服务,完成用户希望在网络上完成的各种工作。
1.1.2 网络数据传输过程
我们平常使用的程序( 或者说软件) 一般都是通过应用层来访问网络的, 程序产生的数据会一层一层地往下传输, 直到最后的网络接口层, 就通过网线发送到互联网上去了。数据每往下走一层, 就会被这一层的协议增加一层包装, 等到发送到互联网上时, 已经比原始数据多了四层包装。 整个数据封装的过程就像俄罗斯套娃。当另一台计算机接收到数据包时, 会从网络接口层再一层一层往上传输, 每传输一层就拆开一层包装, 直到最后的应用层, 就得到了最原始的数据, 这才是程序要使用的数据。
2 传输层通信协议
2.1 TCP
TCP是面向连接的传输协议、可考性传输,建立连接时要经过三次握手, 断开连接时要经过四次挥手, 中间传输数据时也要回复 ACK 包确认, 多种机制保证了数据能够正确到达, 不会丢失或出错。
2.1.1 TCP的3次握手过程
1、 客户端发送 TCP 连接请求
客户端会随机一个初始序列号 seq=x( client_isn) , 设置 SYN=1, 表示这是 SYN 握手报文。 然后 就可以把这个 SYN 报文发送给服务端了, 表示向服务端发起连接, 之后客户端处于同步已发送状态。
2、 服务端发送针对 TCP 连接请求的确认, 服务端收到客户端的 SYN 报文后, 也随机一个初始序列号(server_isn)(seq=y), 设置 ack=x+1, 表示收到了客户端的 x 之前的数据, 希望客户端下次发送的数据从x+1 开始。 设置 SYN=1 和 ACK=1。 表示这是一个 SYN 握手和 ACK 确认应答报文。最后把该报文发给客户端, 该报文也不包含应用层数据, 之后服务端处于同步已接收状态。
3、 客户端发送确认的确认
客户端收到服务端报文后, 还要向服务端回应最后一个应答报文, 将 ACK 置为 1 , 表示这是一个应答报文 ack=y+1 , 表示收到了服务器的 y 之前的数据, 希望服务器下次发送的数据从 y+1 开始。 最后把报文发送给服务端, 这次报文可以携带数据, 之后客户端处于连接已建立 状态。 服务器收到客户端的应答报文后, 也进入连接已建立状态通过这样的三次握手过程, TCP 能够确保双方能够收到对方的请求和回应, 并且双方都知道彼此的初始序列号和确认号。 这样建立起来的连接可以提供可靠的数据传输和顺序控制。
ACK: 确认序号有效。
SYN: 发起一个新连接。
CLOSED: 不在连接状态( 这是为方便描述假想的状态, 实际不存在)
LISTEN: 等待从任何远端 TCP 和端口的连接请求。
SYN_SENT: 发送完一个连接请求后等待一个匹配的连接请求。 syn_sent
SYN_RCVD:这个状态表示接受到了 SYN 报文, 在正常情况下, 这个状态是服务器端的 SOCKET 在建立 TCP连接时的三次握手会话过程中的一个中间状态, 很短暂, 基本上用 netstat 你是很难看到这种状态的, 除非你特意写了一个客户端测试程序, 故意将三次 TCP 握手过程中最后一个 ACK 报文不予发送。 因此这种状态时, 当收到客户端的 ACK 报文后, 它会进入到 ESTABLISHED 状态ESTABLISHED: 表示一个打开的连接, 接收到的数据可以被投递给用户。 连接的数据传输阶段的正常状态。
为什么是三次握手, 为什么不是两次或者四次?
主要原因: 防止已经失效的连接请求报文突然又传送到了服务器, 从而产生错误
如果采用两次握手会出现以下情况:
客户端向服务器端发送的请求报文由于网络等原因滞留, 未能发送到服务器端, 此时连接请求报文失效,客户端会再次向服务器端发送请求报文, 之后与服务器端建立连接, 当连接释放后, 由于网络通畅了, 第一次客户端发送的请求报文又突然到达了服务器端, 这条请求报文本该失效了, 但此时服务器端误认为客户端又发送了一次连接请求, 两次握手建立好连接, 此时客户端忽略服务器端发来的确认, 也不发送数据, 造成不必要的错误和网络资源的浪费。如果采用三次握手的话, 就算那条失效的报文发送到服务器端, 服务器端确认并向客户端发送报文, 但此时
客户端不会发出确认, 由于客户端没有确认, 由于服务器端没有接收到确认, 就会知道客户端没有请求连接。为什么不是四次? 如果三次就能够确定正常连接, 就没有必要在进行确认, 来浪费资源了。
2.1.2 TCP四次挥手过程
ESTABLISHED: 表示一个打开的连接, 接收到的数据可以被投递给用户。 连接的数据传输阶段的正常状态。
FIN_WAIT_1: 等待远端 TCP 的连接终止请求, 或者等待之前发送的连接终止请求的确认。
FIN_WAIT_2: 等待远端 TCP 的连接终止请求。
CLOSE_WAIT: 等待本地用户的连接终止请求。
CLOSING: 等待远端 TCP 的连接终止请求确认。
LAST_ACK: 等待先前发送给远端 TCP 的连接终止请求的确认( 包括它字节的连接终止请求的确认)
TIME_WAIT: 等待足够的时间过去以确保远端 TCP 接收到它的连接终止请求的确认。
数据传输完毕后, 双方都可释放连接。 最开始的时候, 客户端和服务器都是处于 ESTABLISHED 状态, 然后客户端主动关闭, 服务器被动关闭。
FIN: 断开一个连接标志;
第一次挥手:客户端发出连接释放报文, 并且停止发送数据。 释放数据报文首部, FIN=1, 其序列号为 seq=u( 等于前面已经传送过来的数据的最后一个字节的序号加 1) , 此时, 客户端进入 FIN-WAIT-1( 终止等待 1)状态。
第二次挥手 服务器端接收到连接释放报文后, 发出确认报文, ACK=1, ack=u+1, 并且带上自己的序列号seq=v, 此时, 服务端就进入了 CLOSE-WAIT 关闭等待状态。
第三次挥手 客户端接收到服务器端的确认请求后, 客户端就会进入 FIN-WAIT-2( 终止等待 2) 状态, 等待服务器发送连接释放报文, 服务器将最后的数据发送完毕后, 就向客户端发送连接释放报文, 服务器就进入了LAST-ACK( 最后确认) 状态, 等待客户端的确认。
第四次挥手 客户端收到服务器的连接释放报文后, 必须发出确认, ACK=1, ack=w+1, 而自己的序列号是seq=u+1, 此时, 客户端就进入了 TIME-WAIT( 时间等待) 状态, 但此时 TCP 连接还未终止, 必须要经过 2MSL后( 最长报文寿命) , 当客户端撤销相应的 TCB 后, 客户端才会进入 CLOSED 关闭状态, 服务器端接收到确认报文后, 会立即进入 CLOSED 关闭状态, 到这里 TCP 连接就断开了, 四次挥手完成。
总结:
* 面向连接, 类似我们手机打电话, 不管有没有人说话--通话都计时
* 稳定的长连接通信
* 速度相对来说比较慢
* 一般不容易丢失数据 -- 有链接三次握手
* 以及断开链接的四次挥手
2.2 UDP
UDP 是非面向连接的传输协议, 没有建立连接和断开连接的过程, 它只是简单地把数据丢到网络中, 也不需要 ACK 包确认。 在数据传输过程中延迟小、 数据传输效率高。
当强调传输性能而不是传输的完整性时, 如: 音频和多媒体应用, UDP 是最好的选择。
总结:
* 短链接, 不连接通信
* 相对来说没有 TCP 那么稳定
* 有可能丢失相应数据
* 它的发送速度相对 TCP 来说比较快
3 网络编程的IP地址
IP 地址是 Internet Protocol Address 的缩写, 译为“网际协议地址”。 在因特网上进行通信时, 必须要知道对方的 IP 地址。
1) shell 查看 ip
windows 下: ipconfig
Linux 下: ifconfig
2) ipv4
ipv4 地址是一个 32 位(bit)地址数据(unsigned int)
1> 点分十进制表示 IP
8 位合成一个数值, 用.隔开, 这种表达方式即为点分十进制
例如 点分十进制: 192.168.110.59
0.0.0.0 -- 255.255.255.255
2> ip 由网络号和主机号组成
网络号: 区分局域网
主机号: 区分同一个局域网内不同的设备
IP 地址根据网络 ID 的不同分为 5 种类型
A 类地址: 0.0.0.0-127.255.255.255
第一个字节 IP 网络号, 后三个字节为主机字节
A 类地址你是无法得到的, A 类地址是用于超级公司/国家政府的地址
B 类地址: 128.0.0.0-191.255.255.255
前两个字节为 IP 网络号, 后两个字节为主机字节
一般也适用于大型公司
C 类地址: 192.0.0.0-223.255.255.255
前三个字节为 IP 网络号, 后一个字节为主机地址
D 类地址: 在历史上被叫做多播地址(multicast address), 即组播地址
224.0.0.0 到 239.255.255.255。
E 类地址: 广播地址, 用于研究使用
3> 由于科技发展, 电子设备增多, IP 地址不够用, 出现 ipv6 地址(128 位地址数据) 2^128
4> 子网掩码: 网络号为 1 主机号为 0
例如: 192.168.110.123
子网掩码: 255.255.255.0 ( c 类)
5> 网关: 网络号不变, 主机号为 0
例如: 192.168.110.123
网关: 192.168.110.0 ( C 类 IP)
4 端口
一台计算机可以同时提供多种网络服务, 例如 Web 服务( 网站) 、 FTP 服务( 文件传输服务) 、 SMTP 服务( 邮箱服务) 等, 仅 5 有 IP 地址, 计算机虽然可以正确接收到数据包, 但是却不知道要将数据包交给哪个网络程序来处理, 所以为了区分不同的网络程序, 计算机会为每个网络程序分配一个独一无二的端口号( PortNumber)
端口的数据类型: unsigned short 范围: 0-65535
端口分为
1) 知名端口号
知名端口号是系统程序使用的端口号. 知名端口范围从 0 到 1023.
2) 动态端口号
动态端口号是普通程序使用的端口号. 动态端口的范围是从 1024 到 65535. 当这个程序关闭时,
同时也就释放了所占用的端口号, 一般建议使用 10000 以上。 10000-65535
5 TCP 协议编程框架
5 套接字
套接字是计算机之间进行通信的一种约定或一种方式。 通过 socket 这种约定, 一台计算机可以接收其他计算机的数据, 也可以向其他计算机发送数据。
socket 的典型应用就是浏览器: 浏览器获取用户输入的 URL( 统一资源定位符) , 向服务器发起请求,服务器分析接收到的 URL, 将对应的网页内容返回给浏览器, 浏览器再经过解析和渲染, 就将文字、 图片、视频等元素呈现给用户。
UNIX/Linux 中的 socket 是什么? UNIX/Linux 程序在执行任何形式的 I/O 操作时, 都是在读取或者写入一个文件描述符。 一个文件描述符只是一个和打开的文件相关联的整数, 它的背后可能是一个硬盘上的普通文件、 FIFO、 管道、 终端、 键盘、 显示器, 甚至是一个网络连接。
请注意, 网络连接也是一个文件, 它也有文件描述符! 我们可以通过 socket() 函数来创建一个网络连接, 或者说打开一个网络文件, socket() 的返回值就是文件描述符。 有了文件描述符, 我们就可以使用普通的文件操作函数来传输数据了, 网络编程原来就是如此简单!