7. 网络编程
由于计算机网络的迅速发展和互联网的广泛应用。在互联网的发展过程中,人们需要开发各种类型的网络应用程序来满足不同的需求,例如电子邮件、文件传输、网页浏览器等等。 而这些网络应用程序需要通过计算机网络进行数据传输和处理,因此需要有一种标准的网络编程模型和工具来支持它们的开发。Linux作为一种自由和开放的操作系统,拥有丰富的网络编程资源和工具,因此成为了网络编程的重要平台之一。
7.1 TCP/IP协议
- TCP/IP协议是为了解决不同系统的计算机通信而提出的一个标准,不同系统的计算机采用了同一种协议后,就能相互进行系统通信,从而建立网络连接,实现资源共享和网络通信。
7.1.1 分层结构
网络协议通常分不同层次进行开发,每一层分别负责不同的通信功能。一个协议族,比如TCP/IP,是一组不同层次上的多个协议的组合。TCP/IP通常被认为是一个四层协议系统:

应用层(Application Layer):应用层是TCP/IP协议栈的最顶层,提供了应用程序与网络之间的接口。它包含了各种应用协议,如HTTP、FTP、SMTP等。应用层负责处理特定应用程序的通信需求,为应用程序提供数据交换的能力。
传输层(Transport Layer):传输层负责在网络中的主机之间提供端到端的通信。它使用TCP和UDP协议来实现数据的可靠传输和流控制。具体功能如下:
- TCP协议:提供可靠的、面向连接的通信。它负责数据的分段、序列号、重传机制以及拥塞控制。
- UDP协议:提供不可靠的、面向无连接的通信。它更加轻量级,不提供数据的可靠性和有序性,适用于一些实时性要求较高的应用。
网络层(Network Layer):网络层负责在网络中的主机之间提供数据包的传输和路由选择。它使用IP协议来实现分组的传输和寻址。具体功能如下:
- IP协议:定义了互联网中数据包的格式和传输方式。它使用IP地址标识网络上的主机,并通过路由选择算法确定数据包的传输路径。
链路层(Link Layer):链路层负责在物理网络中传输数据帧。它与网络适配器(网卡)直接交互,处理物理层的细节。具体功能如下:以太网(Ethernet)是最常用的链路层协议,它定义了数据帧的格式、介质访问控制和地址解析等。
不同的协议层对数据包有不同的称谓,在传输层叫做TCP段,在网络层叫做 IP 数据报,在链路层叫做以太网帧。
在主机发送端,从传输层开始会把上一层的数据加上一个报头形成本层的数据,这个过程叫数据封装,在主机接收端,从最下层开始,每一层数据就会去掉首部信息,该过程叫数据解封。

7.2 协议簇和地址簇
- 协议簇(Protocol Family)是指一组协议的集合,而地址簇(Address Family)是指网络地址的表示方式。在计算机网络编程中,常用的协议簇和地址簇有以下几种:
7.2.1 协议簇
- IPv4协议簇:包括TCP、UDP、ICMP等协议,使用32位的IP地址标识网络中的主机和路由器。
- IPv6协议簇:与IPv4类似,但使用128位的IP地址。
- Unix域协议簇:用于在同一台计算机上的进程间通信,不需要通过网络传输数据。
7.2.2 地址簇
- IPv4地址簇:使用32位的二进制数表示,通常以点分十进制形式表示,如192.168.0.1。
- IPv6地址簇:使用128位的二进制数表示,通常以冒号分隔的16进制数表示,如2001:0db8:85a3:0000:0000:8a2e:0370:7334。
- Unix域地址簇:使用文件路径表示,如/tmp/my_socket。
- 在套接字编程中,常常需要指定协议簇和地址簇,以便创建相应的套接字。常用的协议簇常量有AF_INET(IPv4协议簇)、AF_INET6(IPv6协议簇)、AF_UNIX(Unix域协议簇)等;
- 常用的地址簇常量有PF_INET(IPv4地址簇)、PF_INET6(IPv6地址簇)、PF_UNIX(Unix域地址簇)等。
7.3 套接字
7.3.1 TCP套接字编程的基本步骤
- TCP套接字编程的基本步骤在客户端和服务端的实现中有所不同。下面分别介绍客户端和服务端的基本步骤:
客户端
- 创建套接字:使用socket函数创建一个TCP套接字。该函数返回一个文件描述符,用于后续的套接字操作。
- 连接服务器:使用connect函数连接服务器端。该函数需要指定服务器端的IP地址和端口号。
- 进行通信:使用套接字进行数据的发送和接收。可以使用send和recv函数进行数据的发送和接收。在发送数据时,需要指定数据的长度和目标地址;在接收数据时,需要指定缓冲区的长度和来源地址。
- 关闭套接字:使用close函数关闭套接字,释放资源。
服务端
- 创建套接字:使用socket函数创建一个TCP套接字。该函数返回一个文件描述符,用于后续的套接字操作。
- 绑定套接字:使用bind函数将套接字与本地IP地址和端口号绑定。如果不需要指定本地IP地址和端口号,则可以省略此步骤。
- 监听套接字:使用listen函数将套接字设为监听状态,等待客户端的连接请求。listen函数指定了队列中等待连接的最大数量。
- 接受连接:使用accept函数等待客户端的连接请求,如果有连接请求则接受该连接,并返回一个新的套接字用于与客户端进行通信。
- 进行通信:使用新的套接字进行数据的发送和接收。可以使用send和recv函数进行数据的发送和接收。在发送数据时,需要指定数据的长度和目标地址;在接收数据时,需要指定缓冲区的长度和来源地址。
- 关闭套接字:使用close函数关闭套接字,释放资源。
- 需要注意的是,客户端和服务端在进行通信时,需要遵循一定的通信协议。通常采用的是一种类似于HTTP的请求-响应协议,即客户端发送请求给服务器端,服务器端接收并处理请求,并将处理结果发送给客户端。