一、基础概述
sendto 与 recvfrom 是 linux udp 通信专属收发函数。因为 udp 是无连接协议,通信双方没有固定对端,每次收发数据都必须手动指定对方 ip 和端口,因此 udp 只能使用这两个函数完成数据传输。
头文件:
#include <sys/socket.h>
二、sendto 函数详解
1. 函数原型
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);2. 参数解析
参数 | 详细说明 |
|---|---|
sockfd | udp 套接字文件描述符,由 socket(af_inet, sock_dgram, 0) 创建 |
buf | 待发送的数据缓冲区 |
len | 需要发送的数据有效长度 |
flags | 标志位,常规开发固定填 0 |
dest_addr | 目标地址结构体,存放对方 ip、端口,需要强转为通用地址类型 |
addrlen | 地址结构体大小,填写 sizeof(struct sockaddr_in) |
3. 返回值
大于 0:成功发送的字节数,udp 一次发送一整个数据报,无粘包、无半包
-1:发送失败,errno 保存错误信息
4. 代码示例(仅使用基础字节序函数)
struct sockaddr_in dest_addr;
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.sin_family = af_inet;
dest_addr.sin_port = htons(8888); // 主机端口转网络大端
inet_aton("127.0.0.1", &dest_addr.sin_addr); // 字符串ip转网络大端
char msg[] = "hello udp";
ssize_t ret = sendto(sockfd, msg, strlen(msg), 0,
(struct sockaddr *)&dest_addr, sizeof(dest_addr));
if(ret == -1)
{
perror("sendto failed");
}5. 函数特性
专门用于 udp 无连接通信,每次发送必须指定目标地址
面向数据报,一次函数调用对应一条完整 udp 报文
不存在 tcp 的粘包、半包问题
tcp 套接字可以调用但无意义,地址参数会被内核忽略,工程中不用
三、recvfrom 函数详解
1. 函数原型
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);2. 参数解析
参数 | 详细说明 |
|---|---|
sockfd | udp 套接字,一般已经完成 bind 端口绑定 |
buf | 数据接收缓冲区 |
len | 缓冲区最大接收长度 |
flags | 标志位,常规填 0 |
src_addr | 输出参数,函数自动填入发送方的 ip、端口信息 |
addrlen | 输入输出参数:调用前赋值结构体大小,调用后更新为真实地址长度 |
3. 返回值
大于 0:成功接收的数据字节数
等于 0:接收到空 udp 报文
-1:接收失败或阻塞出错
4. 代码示例(搭配基础字节序打印)
char buf[1024] = {0};
struct sockaddr_in client_addr;
socklen_t addr_len = sizeof(client_addr);
ssize_t n = recvfrom(sockfd, buf, sizeof(buf)-1, 0,
(struct sockaddr *)&client_addr, &addr_len);
if(n > 0)
{
buf[n] = '\0';
// 网络字节序转主机字节序打印
printf("收到消息:%s,来自 %s:%d\n",
buf,
inet_ntoa(client_addr.sin_addr),
ntohs(client_addr.sin_port));
}5. 函数特性
udp 服务端专属接收函数,可以自动获取客户端地址,用于原路回复数据
默认阻塞,没有数据时程序挂起等待
接收缓冲区小于报文长度时,数据会静默截断丢失,无报错
tcp 场景调用无意义,工程中不使用
四、常用 flags 标志
标志 | 作用 |
|---|---|
0 | 默认常规收发 |
msg_peek | 偷看数据,数据不删除,下次仍可接收 |
msg_nosignal | 不产生 sigpipe 信号,避免程序崩溃退出 |
五、核心易错点总结
recvfrom 的 addrlen 必须传 socklen_t 变量地址,不能传常量、不能传 sizeof 地址
udp 数据没有
\0,接收后必须手动补结束符,否则乱码端口赋值用
htons,端口打印用ntohsip 赋值用
inet_aton,ip 打印用inet_ntoa
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论