UDP Socket编程:视频文件传输后无法正常打开的问题排查
UDP Socket传输MP4文件损坏问题排查与修复方案
核心问题分析
UDP是无连接、不可靠协议,传输文件时出现损坏通常源于以下几点:
- 丢包/乱序:UDP不保证数据包的到达顺序与完整性,MP4作为结构化二进制文件,缺失或错位的字节会直接破坏文件格式。
- 元数据不同步:接收端未明确待接收文件的总大小,提前终止写入或写入多余空数据,导致文件不完整。
- 数据边界处理错误:发送端拆分文件块的大小不合理,或接收端未按正确逻辑拼接数据。
- 缓冲区不匹配:发送/接收缓冲区设置过小,导致数据截断。
代码层面修复步骤
1. 先同步文件总大小(关键)
发送端先将文件总字节数转换为网络字节序发送给接收端,让接收端明确需要接收的总数据量:
// 发送端:获取并发送文件大小 off_t file_size = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); uint64_t net_file_size = htobe64(file_size); // 转换为网络字节序(MacOS原生支持) sendto(sockfd, &net_file_size, sizeof(net_file_size), 0, (struct sockaddr*)&client_addr, sizeof(client_addr)); // 接收端:先接收文件大小 uint64_t net_file_size; socklen_t addr_len = sizeof(server_addr); recvfrom(sockfd, &net_file_size, sizeof(net_file_size), 0, (struct sockaddr*)&server_addr, &addr_len); off_t file_size = be64toh(net_file_size); // 转回主机字节序
2. 引入数据包序号与重传机制
UDP无可靠性保障,必须手动实现序号校验与重传:
定义数据包结构:
typedef struct { uint32_t seq; // 数据包序号 uint32_t data_len; // 本次携带的数据长度 char data[1472]; // 数据缓冲区(MTU适配:1500-20IP头-8UDP头=1472) } UDP_Packet;
- 发送端按序号依次发送每个文件块,等待接收端的确认信号,超时则重传对应序号的数据包。
- 接收端接收后检查序号,若发现缺失则向发送端发送重传请求,按序号将数据写入文件对应位置(而非直接追加)。
3. 确保完整写入文件
接收端累计已接收字节数,达到文件总大小再停止写入:
FILE *fp = fopen("received_test.mp4", "wb"); if (!fp) { perror("fopen failed"); exit(1); } off_t received_bytes = 0; char buf[1472]; while (received_bytes < file_size) { ssize_t recv_len = recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL); if (recv_len <= 0) { perror("recvfrom failed"); break; } fwrite(buf, 1, recv_len, fp); received_bytes += recv_len; } fclose(fp);
注:若使用带序号的数据包,需先将数据按序号写入对应偏移量,避免乱序导致文件结构混乱。
4. 规范文件打开模式
无论发送端还是接收端,都以二进制模式打开文件:
// 发送端打开源文件 int fd = open("video.mp4", O_RDONLY); // 或用标准IO:FILE *fp = fopen("video.mp4", "rb"); // 接收端打开目标文件 FILE *fp = fopen("received_test.mp4", "wb");
验证方法
传输完成后,通过以下方式确认文件完整性:
- 对比文件字节数:
ls -l video.mp4 received_test.mp4
- 校验文件哈希:
md5 video.mp4 md5 received_test.mp4
若哈希值一致,说明文件完整;若不一致,重点排查丢包与重传逻辑。
内容的提问来源于stack exchange,提问作者user24723398
相关产品推荐
相关产品推荐

