【发布时间】:2014-11-26 08:49:40
【问题描述】:
我正在编写一个基于 UDP 的流媒体服务器,遇到了一个奇怪的问题,我确定这只是一个简单的错误,但我找不到解决方案。服务器执行以下操作:
FILE* infile = fopen(inf, "rb");
register int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
int16_t buffer[LENGTH+HEADER];
struct header header;
int16_t data[LENGTH];
uint32_t number = 0;
/*set socket options etc. */
while(!feof(infile)){
fread(data, 1, LENGTH, infile);
/* if i write the contents of data to a file here, the error below occurs*/
fwrite(data, 1, LENGTH, testfile);
/*create a header, encode everything with htons/htonl*/
if(sendto(sock, buffer, LENGTH+HEADER, 0, (struct sockaddr*) &to,
sizeof to) < 0)
/*die*/
}
这似乎有效。我可以解码它并且数据没有损坏。但是,我编写了一个可以工作(或者更确切地说:不工作)的测试客户端,如下所示:
struct sockaddr_in si_other, si_me;
register int s;
unsigned int slen = sizeof(si_other);
int16_t buf[LENGTH+HEADER];
int16_t data[LENGTH];
FILE* file = fopen(of, "wb");
/*open socket, set options, etc. */
while(1){
if(recvfrom(s, (char *)buf, LENGTH+HEADER, 0, (struct sockaddr*) &si_other,
&slen) < 0)
/*die*/
decode(buf, data);
/* If I write the decoded data to a file here, the error below occurs */
fwrite(data, 1, LENGTH, testfile);
if(is_empty(data) == 0){
printf("End signal received.\n");
break;
}
}
现在我的问题。当我使用diff <(xxd test_before) <(xxd test_after) 检查十六进制的测试文件时,我得到了这个(示例差异行):
< 03d5ff0: f3fd f3fd 99fe 99fe 40ff 40ff e7ff e7ff ........@.@.....
---
> 03d5ff0: f3fd f3fd 0000 0000 0000 0000 0000 0000 ................
这意味着数据包数据的最后 12 个字节丢失了。其他一切都很好。
这只是测试代码,所以它并不重要(我猜),但它很奇怪,我想知道为什么。
有什么想法吗?
编辑:
我现在已经从答案中尝试了一些方法,到目前为止还没有得到任何结果。我会继续努力。
编辑 2:
代码在不同的机器上工作。我不确定问题是什么,但它似乎对除我以外的任何人都有效。很抱歉占用您的时间,感谢您对如何改进代码等提出的所有友好建议!
提前致谢, 卡森
【问题讨论】:
-
如果你想发送/接收
LENGTH+HEADER数量的 int16_t,你必须通过(LENGTH+HEADER)*sizeof(int16_t)到 sendto/recvfrom。 (或者在这种特殊情况下只是sizeof buffer) -
顺便说一句:不要这样做:
while(!feof(infile)){feof() 的工作方式与您的想法不同;它在读取操作失败后返回非零。 -
函数 encode() 最有可能改变数据的长度,尤其是当数据中有一个密钥后。如您的代码中所写, sendto() 和 recvfrom() 函数并未考虑此字节数变化。当它应该是 2*u16 计数时,您的代码给出了 u16 计数。
标签: c sockets stream udp recvfrom