一、网络通信基础
在不同主机间进行通信是网络编程的核心问题。为实现网络通信,需要在物理层面和软件层面都建立通路。
-
物理通路:
- 包括有线和无线连接方式,如 5G、4G 以及星链等,为信息传输提供物理层面的支持,以二进制数据一位一位进行传输。
-
软件通路:
- 由国际标准化组织 ISO 于 1981 年制定的开放系统互连参考模型(OSI/RM),旨在解决不同体系结构网络的互联问题。
- OSI 七层模型包括物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。各层有其特定的功能和规范,如物理层规定物理层面的电气和机械特性,传输层控制传输过程保证数据完整可靠等。
- 实际应用中主要是 tcp/ip 模型,分为应用层、传输层、网络层、数据链路层和物理层,或者四层模型,即应用层、传输层、网络层和网络接口层。
二、IP 与端口号
-
IP 地址:
- IP 用来标识网络中的一台主机,本质是 32 位整型数值,以点分十进制表示,如 192.168.1.149。IP 地址由网络号和主机号组成,网络号表示所处的网络,主机号表示能容纳的主机。
-
掩码(mask):
- 用于确定 IP 地址的网络部分和主机部分。通过与 IP 地址进行按位与运算,可以得到网络地址。
-
端口号:
- 用来表示主机中某一个具体进行网络通信的进程。端口号是 16 位数值(unsigned short),范围为 0~65535。端口号分为众所周知端口(1~1023)、已登记端口(1024~49151)和动态或私有端口(49152~65535)。
三、网络编程协议
-
TCP 协议:
- 传输控制协议,是一种面向连接的传输层协议,能提供高可靠性通信,包括数据无误、无丢失、无失序、无重复到达。适用于对传输质量要求较高以及传输大量数据的通信场合,如 QQ 等即时通讯软件的用户登录账户管理功能。特点包括面向连接、可靠传输和面向字节流。
-
UDP 协议:
- 用户数据报协议,是不可靠的无连接协议。在数据发送前不需要进行连接,可进行高效率的数据传输。适用于发送小尺寸数据、在应答较困难的网络中使用、广播 / 组播式通信以及即时通讯软件的点对点文本通讯和音视频通讯、网络多媒体服务等。特点为不可靠、无连接、数据报。
- 用户数据报协议,是不可靠的无连接协议。在数据发送前不需要进行连接,可进行高效率的数据传输。适用于发送小尺寸数据、在应答较困难的网络中使用、广播 / 组播式通信以及即时通讯软件的点对点文本通讯和音视频通讯、网络多媒体服务等。特点为不可靠、无连接、数据报。
四、编程模型
-
C/S 模型(客户端 / 服务器模型):
- 客户端是主动角色,通过 socket 进行网络通信,使用 sendto 函数发送数据。
- 服务器端是被动角色,同样使用 socket,通过 recvfrom 函数接收数据。
-
B/S 模型(浏览器 / 服务器模型):使用通用的浏览器作为客户端。
-
P2P 模型(点对点传输):实现直接的点对点通信。
五、网络编程接口与函数
-
socket 函数:
int socket(int domain, int type, int protocol);
用于程序向内核提出创建一个基于内存的套接字描述符。- 参数 domain 表示地址族,用于确定 socket 的通信范围,如 PF_INET(或 AF_INET)用于互联网程序,PF_UNIX(或 AF_UNIX)用于单机程序。
- 参数 type 表示套接字类型,如 SOCK_STREAM 对应 TCP,SOCK_DGRAM 对应 UDP,SOCK_RAW 对应 IP。
- 参数 protocol 表示协议,通常为 0 表示自动适应应用层协议。
-
sendto 函数:
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
用于发送数据。- 参数 sockfd 是用于通信的 socket 对应的文件描述符。
- 参数 buf 是要发送的数据所在的空间,len 表示发送的字节数,flags 默认为 0,dest_addr 是要发送到的地址(网络地址包括 IP 和端口号),addrlen 是 dest_addr 参数的长度。
-
数字转换函数:
uint32_t htonl(uint32_t hostlong);
和uint16_t htons(uint16_t hostshort);
用于主机转网络。uint32_t ntohl(uint32_t netlong);
和uint16_t ntohs(uint16_t netshort);
用于网络转主机。
-
字符串转换函数:
in_addr_t inet_addr(const char *cp);
用于主机转网络。char *inet_ntoa(struct in_addr in);
用于网络转主机并以 ASCII 码形式表示。