我想发送一个字节数组X次,直到达到缓冲区大小。我的客户端发送字节数组,直到缓冲区大小已满。但问题是数据包丢失,服务器只收到8/10的缓冲区大小。
客户端:
while(writeSize < bufferSize)
{
bytes_sent += sendto(servSocket, package, sizeof(package), 0, (struct sockaddr *)&server, sizeof(server));
writeSize+= sizeof(package);
}
服务器:
while(packetSize < bufferSize)
{
bytes_recv += recvfrom(servSocket, package, sizeof(package), 0, (struct sockaddr*)&client, &size);
packetSize += sizeof(package);
printf("Bytes recieved: %d\n", bytes_recv);
}
我无法真正想出这个问题的解决方案。当客户端发送了所有软件包,并且服务器遭受软件包丢失时,while循环将不会结束,有什么想法我可以解决这个问题吗?
非常感谢
答案 0 :(得分:2)
哼。您正在使用UDP。对于这个协议,如果有需要,它可以丢弃数据包。因此,就“发送的内容将会到达”而言,这是不可靠的。您在客户端需要做的就是检查所有需要到达的数据包,如果没有,请礼貌地与您的服务器交谈以重新发送您未收到的数据包。要实现这些东西并不是那么容易,你最终可能会得到一个解决方案,而不仅仅是使用普通的旧tcp-socket,因此我的推荐将是第一个切换到tcp连接的实例。
答案 1 :(得分:2)
如果您必须使用UDP传输大量数据,那么设计一个小的应用程序级协议,以处理可能的数据包丢失和重新排序(这是TCP为你做的一部分)。我会选择这样的东西:
你走了。我们又开始构建TCP ......
答案 2 :(得分:0)
当然TCP是更好的选择,但如果你只有UDP选项,我将数据包装到一个带有sequence和buf_length字段的结构中。
它绝对不是最佳解决方案......它只是处理序列号,以确保数据完全到达并具有正确的顺序。如果没有,只需停止接收数据(它可以做一些更聪明的事情,比如要求发送重新发送片段并重建数据,尽管顺序错误但它会变得非常复杂)
struct udp_pkt_s {
int seq;
size_t buf_len;
char buf[BUFSIZE];
};
发送方:
struct udp_pkt_s udp_pkt;
udp_pkt.seq = 0;
while(writeSize < bufferSize)
{
// switch to the next package block
// ...
memcpy(udp_pkt.buf, package);
udp_pkt.buf_len = sizeof(package);
udp_pkt.seq++;
bytes_sent += sendto(servSocket, &udp_pkt, sizeof(udp_pkt_s), 0, (struct sockaddr *)&server, sizeof(server));
writeSize += sizeof(package);
}
接收方:
last_seq = 0;
while(packetSize < bufferSize)
{
bytes_recv += recvfrom(servSocket, &udp_pkt, sizeof(udp_pkt_s), 0, (struct sockaddr*)&client, &size);
// break it if there's a hole
if (udp_pkt.seq != (last_seq + 1))
break;
last_seq = udp_pkt.seq;
packetSize += udp_pkt.buf_len;
printf("Bytes recieved: %d\n", udp_pkt.buf_len);
}
答案 3 :(得分:0)
发送后你可以等待sendto缓冲区达到零,你可以在每次sendto调用后使用以下api。
void waitForSendBuffer(void)
{
int outstanding = 0;
while(1)
{
ioctl(socketFd_, SIOCOUTQ, &outstanding);
if(outstanding == 0)
break;
printf("going for sleep\n");
usleep(1000);
}
}