【网络编程】套接字入门:网络字节序与套接字种类剖析

文章目录
- 一. 前言
- 二. 套接字
- 三. 网络字节序
- 四. 套接字种类
一. 前言
在网络通信构建的数字世界里,套接字是程序叩响网络大门的密钥,网络字节序是数据跨平台流转的通用语言,而套接字种类则决定了通信的“战术风格”——是追求 TCP 的可靠稳行,还是 UDP 的高效灵活?
本文将从这三个核心维度切入,拆解网络编程的底层逻辑:从套接字的创建与通信流程,到字节序转换的隐蔽陷阱,再到不同套接字类型的适用场景,逐步揭开网络通信的运行密码。无论你是初涉网络开发的学习者,还是希望深耕协议细节的开发者,这些基础命题的剖析,都将为你搭建起从理论到实践的桥梁,让网络编程的复杂原理变得清晰可触。
本文将分为三部分:
- 套接字;
- 网络字节序;
- 套接字类型。
二. 套接字
- 网络协议栈中的下三层(传输层,网络层,数据链路层)是负责保障数据安全可靠传送给远程主机的;
- 用户的的程序通过下三层完成数据的发送和接收。
我们都知道数据在进行参数的时候要进行封装和解包,那么在接收方的传输层解包后他怎么知道交给上层的哪一个程序???
操作系统中的每一个应用都一个端口号Port来记录进程的唯一性,通过在报头中添加目的进程的端口号就可以让对方知道要将信息交付给哪一个程序。
- 一般在对服务端的端口号是固定的,一般内置在用户端,让用户端可以直接找到服务器的地址,来从服务器中获取我们想要的数据。
- 但是对于客户端来说,一般不能指定端口号,端口号由操作系统来分配,因为用户并不知道操作系统中那些端口号没有使用;在报文中添加源端口号就可以让接收消息的一方也能找到自己的进程位置。
IP使用来标识全网中唯一的一台主机的,而端口号用来标识一台主机上唯一的进程。
因此IP + Port就可以标定全网唯一的进程。这种定位进程的方式就称为套接字。、
在操作系统中PID也能定位唯一的进程呀,为什么不使用PID + IP来进行定位???
也可以这样进行定位,但是为了将网络与系统进行解耦,使用新的端口号来标识进程。
在操作系统中一个哈希表,使用key-value
的模式来将端口号与进程的task_struct
结构体对象进行绑定。
- 注意:一个进程可以绑定多个端口号,从多个端口接收数据;但是一个端口号只能绑定一个进程,否则就不知道先上面的哪一个进程交付数据了。
三. 网络字节序
一个机器有大端,也有小端,两者存放数据的形式恰好相反,那么发送到网络中的数据形式是什么样的???
- 按照自己机器的数据存放方式进行发送,如果发送方是大端,接收方是小端,就会导致接收方解析出来的数据是错误的,根本看不懂;
能不能在报头中告诉对方自己是大端还是小端的???
不行,本来对方就不知道如何解析数据,而你在这些解析不出来的数据中告诉对方如何解析。
为了方便,TCP/IP规定,网络字节流中统一采用大端字节序,即低地址放高字节。
四. 套接字种类
在套接字编程中,根据通信范围和协议层次,主要可分为域间套接字、网络套接字和原始套接字三类,它们的应用场景和工作方式有显著区别:
原始套接字(Raw Socket):
- 直接操作底层网络协议(如 IP、ICMP、以太网),可读取 / 构造原始数据包。
网络套接字(Network Socket): - 用于不同主机间的进程通信,依赖 TCP/IP 等网络协议栈
域间套接字(Unix Domain Socket): - 仅用于同一主机内的进程间通信(IPC),不依赖网络协议栈,通过操作系统内核实现。
以下是三种套接字使用时的结构体:分别对应原始套接字,网络套接字和域间套接字
其结构体字段如下:
struct sockaddr {sa_family_t sa_family; /* address family, AF_xxx */char sa_data[14]; /* 14 bytes of protocol address */
};struct sockaddr_in {sa_family_t sin_family; /* Address family */unsigned short int sin_port; /* Port number */struct in_addr sin_addr; /* Internet address *//* Pad to size of `struct sockaddr'. */unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -sizeof(unsigned short int) - sizeof(struct in_addr)];
};struct sockaddr_un {sa_family_t sun_family; /* AF_UNIX */char sun_path[UNIX_PATH_MAX]; /* pathname */
};
以上三种套接字如果直接提供接口,就会出现3种不同但是类似的接口,因此为了方便在使用接口的时候统一传struct sockaddr
,通过访问前两个字节来确定类型,进而使用不同类型的结构体进行操作。