You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:47:19