一、套接字通信
内核开发工程师将网络部分的头文件存储到一个专门的目录include/net中,而不是存储到标准位置include/linux。
计算机之间通信是一个非常复杂的问题:
- 如何建立物理连接?
- 使用什么样的线缆?
- 通信介质有那些限制和特殊的要求?
- 如何处理传输错误的问题?
- 如何识别计算机网络中的每一台计算机?
- 如果两台计算机通过其他计算机连接,二者之间的数据是如何进行交换?
- 如何查找最佳的路由?
- 如何打包数据,使它不依赖于特定计算机的特性?
1.ISO/OSI和TCP/IP参考模型
ISO设计一种参考模型,定义组成网络的各个层,该层由7层组成,成为OSI(开放系统互联)模型如下:
- 应用层:网络服务与最终用户的接口;
- 表示层:数据的表示、安全及压缩;格式(jpeg, ascii 等);
- 会话层:建立、管理及终止传话;
- 传输层:定义传输数据的协议端口,以及流控和差错校验;(数据包一旦离开网卡进入网络传输层)
- 网络层:进行逻辑地址建立、实现不同网络之间的路由选择;
- 数据链路层:建立逻辑连接、进行硬件地址寻址、差错检验等功能(由底层网络定义协议),将比特组合成字节进而组合成帧,用 MAC 地址访问介质,错误发现但不能纠正。
其中核心基本术语如下:
- 数据帧(Frame):指起始点和目的点都是数据链路层的信息单元。
- 数据包(Packet):指起始点和目的地是网络层的信息单元。
- 数据报(Datagram):指起始点和目的地都使用无连接网络服务的网络层的信息单元。
- 段(Segment):指起始点和目的地都是传输层的信息单元。
- 消息(Message):指起始点和目的地都在网络层以上的信息单元(经常在应用层)。
- 元素(Cell):指的是一种固定长度的信息,它的起始点和目的地都是数据链路层。元素通常用于异步传输模式(ATM)和交换多兆位数据服务(SMDS)网络等交换环境。
- 数据单元(Data unit):常用的数据单元有服务数据单元(SDU)、协议数据单元(PDU)。
- 数据帧:帧数据由两部分组成:帧头部和帧数据,帧头部包括接收方主机物理地址的定位及其它网络信息,帧数据区含有一个数据体。
- IP 数据体由两个部分组成:数据体头部和数据体的数据区,数据体头部包括 IP 源地址和 IP 目标地址及其它信息,数据体的数据区包括用户数据协议、传输控制协议,还有数据包及其它信息。
1. 数据帧(Frame)
讲解:数据链路层的信息单元,负责在相邻设备间传输数据,包含物理地址(如 MAC 地址)等链路层信息。
例子:好比快递包裹在某个快递网点内部流转。包裹上贴着收件网点的地址标签(类似 MAC 地址),快递员按这个标签在网点内传递包裹,这个带标签的包裹就像数据帧。2. 数据包(Packet)
讲解:网络层的信息单元,关注逻辑地址(如 IP 地址),用于不同网络间的路由选择。
例子:假设快递要从北京发往上海,快递系统根据目的地城市(类似 IP 地址)规划运输路线,这个按城市地址规划路线运输的快递包裹,就是数据包。3. 数据报(Datagram)
讲解:网络层无连接服务的信息单元,发送方不确认接收方是否准备好,类似 “发了就不管”。
例子:像寄平信,写信人把信投入邮筒后,不跟踪信是否送达、是否丢失,只负责发送,这封信就像数据报。4. 段(Segment)
讲解:传输层的信息单元,负责拆分大数据,确保可靠传输(如 TCP 协议分段)。
例子:传输一部 2GB 的电影时,传输层会把电影拆分成多个小段(类似拆分成多个小文件),每个小段添加传输控制信息(如编号),这些小段就是段。5. 消息(Message)
讲解:网络层以上(常为应用层)的信息单元,直接面向用户需求。
例子:用微信发送一段文字 “你好”,这段文字对用户是直观的信息,应用层处理后发送,这个文字内容就是消息,用户不关心底层如何传输。6. 元素(Cell)
讲解:数据链路层的固定长度信息单元,用于 ATM 等交换网络(与可变帧长的传统以太网相比,ATM固定心愿长度传输更适用于实时性、稳定性要求极高的业务;但因技术复杂、成本高,逐渐被以太网等技术取代,目前更多用于特定专业领域),传输高效、规则。
例子:像标准化的货柜,每个货柜大小、规格固定(固定长度)。在 ATM 网络中,数据像货物一样被装进这些固定规格的货柜传输,确保快速交换,这个货柜就是元素。7. 数据单元(SDU、PDU)
- 服务数据单元(SDU):上层协议交给下层处理的数据,关注 “服务内容”。
例子:用户在网盘上传文件,文件内容就是 SDU,网盘底层协议(如 HTTP)会处理它。- 协议数据单元(PDU):加入协议控制信息后的数据单元,关注 “协议处理”。
例子:还是上传文件,底层协议给文件添加头部信息(如传输规则、地址),组合后的整体(文件 + 头部)就是 PDU,类似给文件装个 “协议信封” 再发送。
各层执行的任务:
主机到网络层负责将信息从一台计算机传输到远程计算机。它处理传输介质的物理性质,并将数据流换分为定长的帧,以便在发生传输错误时重传数据块。假设几台电脑共享同一传输线程,网络接口卡必须有唯一一个ID号,MAC地址。
IP使用一定格式的地址来寻址计算机,比如192.168.186.138,这些地址由正式注册权威机构或提供者分配(有时为动态的)。
2.创建套接字
套接字不仅可以用于各种传输协议的IP连接,也可以用于内核支持的所有其他地址和协议类型(例如:IPX、Appletalk、本地UNIX套接字,还有在<socket.h>中列出的许多其他类型)。
- sa_family:是地址家族,一般都是以 AF_XXX 形式出现,比如大多数都是用 AF_INET,代表 TCP/IP 协议中用于ipv4的地址家族。
- Sa_data:是 14 字节协议地址。这个数据结构用做 bind, connect, recvfrom, sendto 等函数的参数,指明地址信息。
short sin_family; // 一般是指:AF_INET 地址族 PF_INET 协议族
unsigned short sin_port;// 端口号(必须要采用网络数据格式,普通数字大家可以使用 htons () 函数转换成网络数据格式的数字)
struct in_addr sin_addr; // IP 地址 32 位
unsigned char sin_zero [8]; // 它没有实际意义,只是为了跟 sockaddr 结构在内存中对齐
in_addr_t s_addr就是存储32位的ipv4地址,明确区分IPv4地址与其他数据,避免直接操作原始整数,并与特定API兼容(如bind、connect)。
BSD 网络软件中包含两个重要的函数:inet_addr,inet_ntoa。用来在二进制地址格式和点分十进制字符串格式之间转换,仅支持 IPv4。也有两个函数同时支持 IPv4 和 IPv6:inet_ntop, inet_pton。
3.使用套接字
简要说明套接字如何表示到内核网络子系统的接口,设计简短程序。例如简单的并发服务器模型如下图所示。在服务器端,主程序提前构建多个子进程,当客户端的请求到来的时候,系统从进程池中选取一个子进程处理客户端的连接,每个子进程处理一个客户端的请求,在全部子进程的处理能力得到满足之前,服务器的网络负载是基本不变的。
TCP 并发服务器,在处理客户端请求之前,程序先分叉为 3 个子进程,对应多个客户端的请求,由多个子进程进行处理。与循环服务器相比较,并发的 TCP 程序,在处理客户端请求的时候,不再简单地使用一个 while 进行客户端请求的串行处理,而是 fork () 一个进程,将客户端的请求放到一个进程中进行处理。
(1)server.c
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#define BUFFLEN 1024
#define SERVER_PORT 8888
#define BACKLOG 5
#define PIDNUMB 3
static void handle_connect(int s_s)
{
int s_c;
struct sockaddr_in from;
socklen_t len = sizeof(from);
while(1)
{
s_c = accept(s_s, (struct sockaddr*)&from, &len);
time_t now;
char buff[BUFFLEN];
int n = 0;
memset(buff, 0, BUFFLEN);
n = recv(s_c, buff, BUFFLEN,0);
if(n > 0 && !strncmp(buff, "TIME", 4))
{
memset(buff, 0, BUFFLEN);
now = time(NULL);
sprintf(buff, "%24s\r\n",ctime(&now));
send(s_c, buff, strlen(buff),0);
}
close(s_c);
}
}
void sig_int(int num)
{
exit(1);
}
int main(int argc, char *argv[])
{
int s_s;
struct sockaddr_in local;
signal(SIGINT,sig_int); //捕获ctrl+C,使用sig_int函数处理
s_s = socket(AF_INET, SOCK_STREAM, 0);
memset(&local, 0, sizeof(local));
local.sin_family = AF_INET;
local.sin_addr.s_addr = htonl(INADDR_ANY);
local.sin_port = htons(SERVER_PORT);
bind(s_s, (struct sockaddr*)&local, sizeof(local));
listen(s_s, BACKLOG);
pid_t pid[PIDNUMB];
int i =0;
for(i=0;i<PIDNUMB;i++)
{
pid[i] = fork();
if(pid[i] == 0)
{
handle_connect(s_s);
}
}
while(1);
close(s_s);
return 0;
}
(2)client.c
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#define BUFFLEN 1024
#define SERVER_PORT 8888
int main(int argc, char *argv[])
{
int s;
struct sockaddr_in server;
char buff[BUFFLEN];
int n = 0;
s = socket(AF_INET, SOCK_STREAM, 0);
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(SERVER_PORT);
connect(s, (struct sockaddr*)&server,sizeof(server));
memset(buff, 0, BUFFLEN);
strcpy(buff, "TIME");
send(s, buff, strlen(buff), 0);
memset(buff, 0, BUFFLEN);
n = recv(s, buff, BUFFLEN, 0);
if(n >0){
printf("TIME:%s",buff);
}
close(s);
return 0;
}
4.数据报套接字
UDP是建立在IP连接之上的第二种广泛使用的传输协议。UDP表示User Datagram Protocal(用户数据报协议)。UDP通常用于视频会议、音频流以及类似的服务。
UDP 与 TCP 有所不同
● UDP 是面向分组的,在发送数据之前,无须建立显式的连接;
● 分组可以在传输期间丢失,不保证数据一定能够到达其目的地;
● 分组接收的次序不一定与发送的次序相同。
二、网络分层模型
1.模型
内核网络子系统的实现与刚介绍的TCP\IP参考模型非常相似。相关的C语言代码划分为不同层次,各层次都有明确定义的任务,各个层次只能通过明确定义的接口与上下文紧邻的层次通信。这种做法的好处在于,可以组合使用各种设备、传输机制和协议。
2.历史上的协议
一、AppleTalk 协议
1. 背景与历史
开发者:Apple 公司(1985年推出)。
用途:专为早期 Macintosh 计算机 设计的局域网协议,支持文件共享、打印服务等。
现状:已被 TCP/IP 取代,现代 macOS 不再原生支持。
2. 协议组成
DDP(Datagram Delivery Protocol):
作用:网络层协议,提供无连接的数据报传输(类似 IP)。
寻址:使用 网络号 + 节点号(如
Network 100, Node 5
)。ATP(AppleTalk Transaction Protocol):
作用:传输层协议,提供可靠的事务处理(类似 TCP)。
特点:基于请求-响应模型,确保数据完整性。
其他协议:
ZIP(Zone Information Protocol):管理逻辑网络分区(Zone)。
NBP(Name Binding Protocol):将设备名解析为网络地址。
3. 网络拓扑
物理层:支持 LocalTalk(专用串行接口,速度 230 Kbps)、EtherTalk(基于以太网)。
局限性:低速、封闭生态,难以适应互联网时代需求。
二、IPX/SPX 协议
1. 背景与历史
开发者:Novell 公司(1980年代)。
用途:为 Novell NetWare 网络操作系统设计的核心协议。
现状:逐渐被 TCP/IP 取代,Windows 通过 NWLink 兼容 IPX/SPX。
2. 协议组成
IPX(Internetwork Packet Exchange):
作用:网络层协议,提供无连接的数据包路由(类似 IP)。
寻址:使用 网络号 + 节点号(MAC地址)(如
Network 0x1A2B, Node 00:1A:2B:3C:4D:5E
)。SPX(Sequenced Packet Exchange):
作用:传输层协议,提供面向连接的可靠传输(类似 TCP)。
特点:支持数据分段、按序传递和重传机制。
3. 优势与局限
优势:
高效路由:IPX 的路由协议(RIP)简单高效,适合局域网。
即插即用:节点自动获取网络号,无需手动配置。
局限:
缺乏互联网兼容性:IPX 地址格式与 IP 不兼容,无法直接接入互联网。
协议臃肿:SPX 的可靠性机制增加了开销。
三、SDLC 与 HDLC 协议
1. SDLC(Synchronous Data Link Control)
背景:IBM 为 SNA(Systems Network Architecture) 设计的数据链路层协议。
特点:
同步传输:时钟信号同步数据帧。
拓扑支持:点对点、多点(轮询机制)。
帧格式:帧头 + 数据 + CRC 校验 + 帧尾。
应用场景:早期 IBM 大型机与终端通信。
2. HDLC(High-Level Data Link Control)
背景:基于 SDLC 改进,由 ISO 标准化(ISO 13239)。
改进点:
协议独立性:支持多种网络层协议。
帧类型扩展:新增监控帧(Supervisory Frame)和无编号帧(Unnumbered Frame)。
多点连接优化:支持平衡模式(两台设备平等通信)。
应用场景:广域网(如 PPP 协议基于 HDLC 设计)、路由器间通信。
3. 关键对比
特性 SDLC HDLC 标准化 IBM 私有协议 ISO 国际标准(ISO 13239) 拓扑支持 主从模式(Primary-Secondary) 平衡模式(Peer-to-Peer) 帧类型 仅信息帧和控制帧 信息帧、监控帧、无编号帧 适用性 专用于 SNA 网络 通用广域网和数据链路层
四、协议在 OSI 模型中的位置
协议 OSI 层级 核心功能 AppleTalk 网络层(DDP)
传输层(ATP)数据报传输、可靠事务处理 IPX 网络层 数据包路由与寻址 SPX 传输层 可靠连接与数据分段 SDLC/HDLC 数据链路层 帧同步、错误检测、流量控制
五、为何这些协议被淘汰?
TCP/IP 的崛起:
开放性:TCP/IP 是开放标准,跨平台兼容性强。
互联网支持:IP 地址体系天然适配全球互联网。
技术局限性:
AppleTalk 和 IPX 的封闭生态难以扩展。
SDLC/HDLC 复杂度高,被更简单的 PPP、以太网取代。
硬件演进:
高速以太网和无线网络需要更高效的协议栈。
3.各协议层的数据划分为首部和数据
首部部分包含了与数据部分有关的元数据(目标地址、长度、传输协议类型等),数据部分包含有用数据(或净荷)。传输的基本单位是帧,网卡以帧为单位发送数据。帧首部部分的主要数据项是目标系统的硬件地址,这是数据传输的目的地,通过电缆传输数据时也需要该数据项。
高层协议的数据在封闭到以太帧时,将协议产生的首部和数据元二组封装到帧的数据部分。
以太网帧中,通过 TCP/IP 传输 HTTP 数据如下: