套接字编程UDP
1.创建套接字
int socket(int domain, int type, int protocol);
第一个参数,底层用的ip报文统一使用的网络协议都是AFIN

第二个参数,面向流的传输协议

SOCK_DGRAM(数据报套接字类型):支持数据报(无连接、不可靠且具有固定最大长度的消息 )
第三个参数,设置为0
创建成功返回一个文件描述符,创建失败返回-1


2.绑定socket信息,ip和端口
2.1 填充sockaddr_in 结构体
IP信息和端口信息一定要发送到网络
(1)本地格式转化成网序列
local.sin_port = htons(_port);
将本地字节序(也叫主机字节序 )的端口号,转换为网络字节序(大端序 高字节存低地址,低字节存高地址),从而让端口号能在网络通信中正确识别和传输
eg:主机是小端序(如常见的 x86 架构 ),_port 的值是 8080(十进制 ),在主机内存中以小端序存储(低字节在前 ),二进制可能表示为 0x1F 0x20(十六进制拆分 )。经过 htons 转换后,会变成大端序的 0x20 0x1F ,然后赋值给 local.sin_port ,满足网络字节序要求
(2)ip也是一样
1. ip转化为4字节
2. 4字节转化为网络序列
1.点分十进制 -> 4字节二进制(主机字节序)
eg:IP 地址 192.168.1.100
192 -> 11000000
168 -> 10101000
1 -> 00000001
100 -> 01100100
得到32位二进制 (4字节)
11000000 10101000 00000001 01100100
2. 4字节 -> 大端序
就能存到 sockaddr_in 结构体的 sin_addr.s_addr 成员里,供网络操作使用
local.sin_addr.s_addr = inet_addr(_ip.c_str());
函数申明 in_addr_t inet_addr(const char *cp);
在实际编程中,我们不需要手动写 in_addr_t inet_addr(const char *cp); 这个声明,而是通过包含头文件 #include <arpa/inet.h> 来获取该函数的声明
函数调用 local.sin_addr.s_addr = inet_addr(_ip.c_str());
local.sin_addr.s_addr = inet_addr("192.168.1.100");

不管是内网还是公网的客户端,都能访问到服务,就可以用 INADDR_ANY ,不用关心具体绑定哪个 IP
INADDR_ANY 的核心作用就是让服务器「绑定到本机所有可用的网络接口」,从而实现:
无论客户端通过服务器的公网 IP、内网 IP 还是本地回环地址(127.0.0.1) 发送请求,只要端口正确,服务器都能接收到。
无需提前知道服务器有哪些 IP 地址(比如服务器可能有多个网卡,或 IP 是动态分配的),简化配置
recvfrom 和 sendto 函数
服务器要显示bind,ip和端口号必须是众所周知且不能轻易改变的
1. 收消息,客户端要给服务器发消息,为了让服务端处理数据
recvfrom 接收数据
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);

client的bind
client要访问目标服务器,需要知道服务器ip和端口,而客户端和服务器是同一家公司写的,就能知道
客户端需要bind即使是客户端,发送数据时也需要一个「源端口」,让服务器能通过 recvfrom 获取客户端的端口。但不要显示地bind,首次发消息,os会自动给client进行bind,os知道ip,os随机选择端口号,只要端口号是唯一的就可以
(1)服务端必须「显式绑定」
服务端需要一个固定、已知的端口(比如 80、8080),让客户端能主动连接。因此必须手动 bind:
(2)客户端可以「隐式绑定」
客户端不需要固定端口(端口由系统自动分配),因此可以省略 bind 操作。当客户端第一次调用 sendto 或 recvfrom 时:
操作系统会自动为客户端分配一个随机的空闲端口(通常在 1024~65535 范围内)
同时自动绑定客户端的 IP(通常是本机 IP,如 192.168.1.100)
操作系统会自动完成以下步骤:
检查客户端套接字是否已绑定端口:
如果未绑定,进入「自动绑定流程」。
分配随机端口:
从 1024~65535 中选一个未被占用的端口(类似临时端口分配)。
绑定客户端 IP:
自动绑定到客户端的「默认出网 IP」(可能是 127.0.0.1 或本机真实 IP,由路由策略决定)
