初识网络协议
OSI七层和TCP/IP五层(四层)
应用层 | 应用程序 | 代码实现 |
传输层 | 端到端传输 (如玩家对玩家) | 操作系统内核实现 |
网络层 | 点到点传输 | 操作系统内核实现 |
数据链路层 | 相邻节点之间的传输 (如集散点到集散点) | 硬件和驱动实现 |
物理层 | 底层基础设施 | 硬件和驱动实现 |
p.s. API是传输层给应用层提供的交互接口
传输层的TCP和UDP协议
TCP(Transmission Control Protocol 传输控制协议)和UDP(User Datagram Protocol用户数据报协议)协议是网络传输层中最知名的两个协议,他们的工作特性相差较大,操作系统提供的API也风格迥异。
TCP协议 | UDP协议 | |
有连接 | 无连接 | 有连接表示信息传输时双方都需要在线连接,如打电话;无连接反之,如发短信 |
可靠传输 | 不可靠传输 | 可靠表示发送方可以知道接收方是否收到信息;不可靠反之 |
面向字节流 | 面向数据报 | 以Byte[]为基本单位;以Datagram为基本单位 |
全双工 | 全双工 | 全双工即一个通道双向通信;半双工反之,一个通道只能单向通信 |
大小不限 | 大小受限 | 因为有发送和接受两端的缓冲区所以大小不限;只有接收端缓冲区所以一次最多64K |
应用层协议
XML协议
通过”标签“的形式组织键值对数据,标签名字就是key,标签内容就是value,如:
<request> <words> "hello" </words> </request> |
缺点:很繁琐,标签量大,内容多了之后很乱,网络带宽占用会更高
JSON协议
可以说是XML的优化版本,用大括弧{}[]等来代替了前后的单词标签,括弧内包含多组键值对,用逗号","来分隔键值对,用冒号":"来分割键和值,如:
{ words:{ hello }, preference:{ protein:beaf, vitamin:orange } } |
优点:美观一些
缺点:依旧是有额外的字符串,传输数据量还是很大,消耗带宽多
protobuffer协议
谷歌搞的二进制数据组织格式,带宽占用较低,更高效,也更复杂,适合对运行效率要求较高的场景使用
封装和分用
上述的网络协议分乐很多层,每一层都有很多协议。上层协议调用下层协议,下层协议给上层提供服务。相邻层之间的协议可以交互,不能跨层交互。
封装过程
应用层 | 应用程序内部约定好了应用层协议 | 【应用层内容】 |
传输层 | 协议很多,TCP协议就是给应用层协议加上报头,包括源端口和目的端口 | 【TCP报头】【应用层内容】 |
网络层 | 协议很多,典型是IP协议,将TCP层数据视为载荷然后加在报头,包括源IP和目的IP | 【IP报头】【TCP报头//应用层内容】 |
数据链路层 | 协议很多,典型是”以太网“,以太网协议给网络层数据整体加上帧头(源mac地址、目的mac地址)和帧尾(校验和) | 【帧头】【IP报头//TCP报头//应用层内容】【帧尾】 |
物理层 | 硬件和驱动有很多,典型的是网卡,将数据链路层的数据二进制bit流转换成光/电信号(取决于光纤/网线)进行传输 | 光电版本【帧头//IP报头//TCP报头//应用层内容//帧尾】 |
分用过程
物理层 | 网卡这样的硬件设备将收到的光/电信号转为二进制bit数据后,传递给数据链路层 | 【帧头//IP报头//TCP报头//应用层内容//帧尾】 |
数据链路层 | 根据以太网协议解析,拿到以太网数据帧,去掉帧头和帧尾后,传递给网络层 | 【IP报头//TCP报头//应用层内容】 |
网络层 | 根据IP协议对拿到的载荷解析,获取到IP报头,去掉IP报头后传递给传输层 | 【TCP报头//应用层内容】 |
传输层 | 根据TCP协议对拿到的载荷解析,去掉TCP报头后传递给应用层 | 【应用层内容】 |
应用层 | 对应用层数据报解析,取出信息 | 【显示再界面上的信息】 |
Socket
Socket = 套接字,是TCP/IP协议的路通信的基本操作单元。
对Socket的理解
操作系统给应用程序提供了一组和网络相关的API,程序员可以通过这组API编写代码完成网络编程。对两个进程的应用程序中的通信连接端点进行抽象,抽象出来的对象就是Socket,相当于一个数据的基本单位(这里体现了OOP思想)。
Socket和Packet的关系
进程和进程之间传输需要将数据打包为一份Socket,Packet是Socket里的一部分。
DatagramPacket叫做数据报,DatagramSocket叫做数据报的套接字。
Socket相关的编程通常都是服务器-客户端模型,点击查看简单实现。
Socket的类型
主要有三个类型:流套接字(Stream)、数据报套接字(Datagram)、原始套接字(Raw)
UDP Socket
UDP协议是以数据报套接字(Datagram)为基本传输单位的,作用为实现客户端-服务器的交互。
服务端的任务是提供多个客户端的请求处理及响应,流程如下:
流程简言之为:
客户端:读取用户请求 -> 创建数据报并将请求写入 -> 创建数据报套接字并将数据报传给服务器 -> 通过数据报套接字从客户端获取响应的数据报 -> 解析响应 -> 反馈给用户
服务器:创建数据报套接字并获取来自客户端的数据报 -> 解析数据报并处理相关请求 -> 将处理结果打包进数据报 -> 通过数据报套接字传回给客户端
DatagramSocket和DatagramPacket是主要使用的两个类。
DatagramSocket API
DatagramPacket API
InetSocketAddress API
socket也是一个文件(广义),而一个进程能同时打开的文件有限(文献描述符表有上限),所以对于会创建很多的socket,就需要对不再使用的socket进行关闭,防止持续消耗文件描述符表。而有些socket可能一个进程中只会出现一次,就不需要这个close。