C语言UDP客户端/服务器传输WAV文件:仅半数样本正常发送问题排查
问题定位与解决方案
嘿,我一眼就看出问题出在哪了——你在UDP发送和接收时搞混了数组元素个数和字节数的区别!这就是为什么每次只有前1024个样本能正确传输的核心原因。
核心错误分析
UDP的sendto()和recvfrom()函数的第三个参数都是字节数,而不是你数组里的元素个数。你的缓冲区定义是short buf[BUFLEN2],其中BUFLEN2=2048,每个short类型占2个字节,所以2048个样本对应的字节数是2048 * 2 = 4096字节,但你现在只传了2048字节,刚好是1024个short样本。
客户端代码的问题
看你客户端的sendto调用:
sendto(s, buf, BUFLEN2 , 0 , (struct sockaddr *) &si_other, slen)
这里第三个参数写的是BUFLEN2(2048),但实际需要发送的是样本数×每个样本的字节数。另外还要注意,fread返回的k是实际读取到的样本数,最后一次读取可能不足2048个样本,所以应该用k * sizeof(short)来指定发送的字节数,而不是固定的BUFLEN2 * sizeof(short)。
服务器代码的问题
服务器的recvfrom同样犯了字节数的错误:
recv_len = recvfrom(s, buf, BUFLEN2, 0, (struct sockaddr *) &si_other, &slen);
这里第三个参数是BUFLEN2(2048字节),只能容纳1024个short样本,所以就算客户端发对了,服务器也收不全。
修改后的代码片段
客户端修改
把sendto的调用改成:
while ((k = fread(buf, sizeof(short), BUFLEN2, file)) > 0) { // 用实际读取的样本数计算要发送的字节数 if (sendto(s, buf, k * sizeof(short) , 0 , (struct sockaddr *) &si_other, slen)==-1) { die("sendto()"); } } // 别忘了关闭文件 fclose(file);
另外,建议替换掉已经废弃的gets函数,避免缓冲区溢出:
printf("Enter file address: "); fgets(fileaddress, BUFLEN1, stdin); // 去掉fgets读取到的换行符 fileaddress[strcspn(fileaddress, "\n")] = '\0';
服务器修改
把recvfrom的调用改成:
recv_len = recvfrom(s, buf, BUFLEN2 * sizeof(short), 0, (struct sockaddr *) &si_other, &slen);
可以加上调试打印,确认接收的字节数和样本数:
if (recv_len == -1) { die("recvfrom()"); } printf("Received %d bytes, which is %d samples\n", recv_len, recv_len / sizeof(short));
额外注意事项
- UDP是无连接、不可靠的协议,传输WAV文件时可能会出现丢包、乱序的情况,如果需要可靠传输,你需要自己实现确认、重传和排序机制。
- 测试时可以在服务器端将接收到的样本写入新的WAV文件,对比原文件是否一致,这样能更直观验证修复效果。
内容的提问来源于stack exchange,提问作者Wrath13
相关产品推荐
相关产品推荐

