前言:
在前段时间为了学习网络编程,于是就看了《Linux高性能服务器编程》和《UNIX网络编程卷1:套接字联网API》的部分章节。在第一次看的时候感觉很懵,毕竟以前对网络的了解仅仅局限于七层协议和TCP/IP协议族的简单内容。在看完两本书的第一遍后,打算重新做一下《Linux高性能服务器编程》的笔记,于是又重新快速翻阅了一下。
可能是因为已经对网络编程有初步的了解,在第二次的阅读中对很多第一次看的时候感觉迷糊的地方又有新的理解。看来经典的书还是的多翻几次,每次看都有新的理解。:)
我并没有把所有章节都作为笔记记下,只是把一些感觉比较重要的章节做了笔记。这一系列的内容更多的是我的读书笔记,如果有哪些地方说的不对的,烦请指正。谢谢~
第一章 TCP/IP协议族
1.1 TCP/IP协议族体系结构以及主要协议
与传统的ISO-OSI七层模型相比,主要是把会话,表示和应用视作一层。
数据链路层
ARP协议(Address Resolve Protocol):地址解析协议,主要用于将IP解析成MAC地址
网络层
IP协议(Internet Protocol):因特网协议,根据数据包的目的IP地址来而决定如何投递它。
ICMP协议(Internet Control Message Protocol):因特网控制报文协议,是IP协议的补充,主要用于检测网络连接。
8位类型字段用于区分报文类型,ICMP报文分为两大类:一类是差错报文,主要用来回应网络错误,如目标不可达(类型值为3)和重定向(类型为5);另一类为查询报文,主要用于查询网络信息,比如ping就是使用ICMP查看目标是否可达(类型值为8)。
PS:ICMP协议并非严格意义上的网络层协议,因为它使用处于同一层的IP协议提供的服务。
传输层
主要为应用程序提供端到端的通信,传输层只关心通信的起始端和目的端。
传输层协议主要有三种,TCP,UDP和SCTP
- TCP协议(Transmission Control Protocol):传输控制协议,为应用层提供可靠的,面向连接的和基于流的服务。TCP具有超时重传,数据确认等方式来确保数据的可靠性。使用TCP协议通信的双方必须先建立TCP连接(三次握手),并在内核为其位置一些必须的数据结构,如连接的状态,读写缓冲区及诸多定时器等。当通信结束,双方必须关闭连接以释放这些内核数据(四次挥手)。TCP是基于流的,意味着数据没有边界限制,它将源源不断地从通信的一段流入另一段。
- UDP协议(User Datagram Protoco):用户数据包协议,为应用层提供不可靠,无连接和基于数据报的服务。“不可靠”意味着UDP无法保证数据能正确传到目的端,因此UDP应用需要自己处理数据确认、超时重传等逻辑。UDP协议是无连接的,即通信双方不保持一个长久的联系(UDP也可以调用connect()来存储目的端的地址),因此应用程序每次发送数据都要明确目的端的地址(sendto(),recvfrom函数中都有个参数是作为接受者地址和来源地址输入的)
基于数据包的服务,是相对于流的服务而言,每个UDP数据包都有一个长度,接收端必须以该长度为最小单位将其所有内容一次性读出,否则数据将被截断。 - SCTP书上不讨论。
应用层
应用层负责处理应用程序的逻辑。
1.2 封装
上下层协议的封装情况。
经过TCP 封装后的数据称为TCP报文段,协议为双方维持一个连接,并且在内核中存储相关数据。这部分数据中的TCP头部信息和TCP内核缓冲区数据一起构成了TCP报文段。
当发送端应用程序使用send或write向TCP连接写入数据是,内核中的TCP模块首先把这些数据**复制(意味着有副本)**到与该连接对应的TCP内核发送缓冲区,然后TCP模块调用IP模块的服务,让TCP头部信息和TCP内核发送缓冲区的内容,即TCP报文段,成为IP数据包的数据部分。
而经过UDP封装后的数据称为UDP数据报。UDP无须为应用层数据保存副本,当一个UDP数据包被成功发送之后,内核缓冲区的数据就被丢弃了。如果打算重发,应用程序需要重新将数据从用户空间拷贝到内核空间中的UDP内核发送缓冲区。
1.7 socket和TCP/IP协议族的关系
由于协议族的前三层是在内核中实现,而应用层一般在用户空间实现,所以需要一组系统调用让应用程序能够访问这些协议提供的服务。实现这组系统调用的API主要有socket。
由socket定义的这一组api提供如下两点功能:一是将应用程序数据从用户缓冲区复制到TCP/UDP内核发送缓冲区,以交付内核来发送数据或从内核TCP/UDP内核接收缓冲区中复制数据倒用户缓冲区,以读取数据;二是修改内核中各个协议的某些信息,从而精细地控制底层通信的行为。
总结:即将数据在用户空间与内核空间之间传输及修改位于内核空间的协议信息,控制底层通信行为。