Reputation: 65
I want to send a byte array X times until I've reached the buffer size. My client send the byte array until the buffer size is full. But the problem is packet loss and the server only recieves like 8/10 of the buffer size.
Client:
while(writeSize < bufferSize)
{
bytes_sent += sendto(servSocket, package, sizeof(package), 0, (struct sockaddr *)&server, sizeof(server));
writeSize+= sizeof(package);
}
Server:
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);
}
I can't really come up with a solution with this problem. When the client has sent all the packages, and the server suffers from package loss the while loop won't end, any ideas how I can solve this?
Many thanks
Upvotes: 6
Views: 10164
Reputation: 76
after sendto you can wait for sendto buffer to reach zero, you can use the following api after each sendto call.
void waitForSendBuffer(void)
{
int outstanding = 0;
while(1)
{
ioctl(socketFd_, SIOCOUTQ, &outstanding);
if(outstanding == 0)
break;
printf("going for sleep\n");
usleep(1000);
}
}
Upvotes: 0
Reputation: 84151
If you have to use UDP to transfer a largish chunk of data, then design a small application-level protocol that would handle possible packet loss and re-ordering (that's part of what TCP does for you). I would go with something like this:
Here you go. We started building TCP again ...
Upvotes: 3
Reputation: 6568
Of course TCP would be the better choice but if you only have UDP option i'd wrap the data into a structure with sequence and buf_length field.
It is absolutely NOT an optimal solution... It just take care of sequence number in order to assure the data is totally arrived and with the right order. If not, just stop to receive data (It could do something smarter like ask to the send to resend pieces and rebuild the data despite thw wrong order but it will become really complex)
struct udp_pkt_s {
int seq;
size_t buf_len;
char buf[BUFSIZE];
};
sending side:
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);
}
receiving side:
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);
}
Upvotes: 1
Reputation: 4467
Hmpf. You are using UDP. For this protocol its perfectly ok to throw away packets if there is need to do so. So it's not reliable in terms of "what is sent will arrive". What you have to do in your client is to check wether all packets you need arrived, and if not, talk politely to your server to resend those packets you did not receive. To implement this stuff is not that easy, and you might finally end up with a solution wich might be less performant than just using plain old tcp-sockets, so my recomendation would be in the first instance to switch to a tcp connection.
Upvotes: 3