I'm trying to use a UDP socket in C++ to send data between a client and server as a project in my university. The file I'm trying to send is an HTML document called s.html
. It's 1,814,247 bytes in size.
When the file is sent, I see two different numbers at the client, the first one is the total number of bytes received minus the size of the header of each packet - which is 8 bytes.
It says that I received 1,814,239 bytes "the number written at the right terminal". So, there are 8 bytes that are missing in the receive from function.
The bigger issue is when I try to inspect the file size in its directory, it gives me 1,810,500 bytes, which is far away from the real number.
The structs of packets, data packet and acknowledge packet:
struct ack_packet {
uint16_t chsum;
uint16_t len;
uint16_t ackno;
};
struct packet {
uint16_t chsum;
uint16_t len;
uint16_t seqno;
uint16_t finished;
char data[500];
};
Here is the code of the server part of interest, if not enough for you to understand the problem, tell me and I'll just upload the whole code.
const size_t chunkSize = 500;
for (uint16_t seqno = 0; seqno < fileSize / chunkSize; ++seqno) {
packet pkt;
pkt.seqno = (seqno);
pkt.len = (chunkSize+8);
pkt.chsum = 88; // random now
pkt.finished = 88; // not 1
memcpy(pkt.data, fileContent.data() + seqno * chunkSize, chunkSize);
if(seqno == fileSize / chunkSize - 1 && fileSize % chunkSize == 0)
pkt.finished = 1;
/**
* The real business starts*/
ssize_t b = sendto(newSock, &pkt, pkt.len, 0, &clntAddr, clntAddrLen);
if(b < 0)
perror("sendto() failed");
ack_packet receivedPacket{};
recvfrom(newSock, (void*)&receivedPacket, 6, MSG_WAITALL,&clntAddr, &clntAddrLen);
if((receivedPacket.ackno) != seqno){
seqno--;
}
}
size_t lastChunkSize = fileSize % chunkSize;
if (lastChunkSize > 0) {
packet pkt;
pkt.seqno = fileSize / chunkSize; // Finished
pkt.len = (lastChunkSize);
memcpy(pkt.data, fileContent.data() + fileSize / chunkSize * chunkSize, lastChunkSize);
pkt.chsum = 0;
pkt.finished = 1;
ssize_t b = sendto(newSock, &pkt, pkt.len, 0, &clntAddr, clntAddrLen);
if(b == lastChunkSize)
cout << "Success size" << endl;
ack_packet receivedPacket;
recvfrom(newSock, (void*)&receivedPacket, 2, MSG_WAITALL, &clntAddr, &clntAddrLen);
cout << "Acknowledged message " << receivedPacket.ackno << endl;
}
Here is the code of interest in the client:
int s = 0;
struct sockaddr temp{};
socklen_t sz;
uint16_t waiting_for_package_x = 0;
while(true){
packet receivedPacket{};
numBytes = recvfrom(sock, (void*)&receivedPacket, 508, MSG_WAITALL,
&temp, &sz);
s+=numBytes-8;
if (numBytes < 0)
DieWithSystemMessage("recvfrom() failed");
if(receivedPacket.seqno != waiting_for_package_x){
cout << receivedPacket.seqno << " " << waiting_for_package_x << endl;
exit(-1);
}
waiting_for_package_x++;
outputFile.write(receivedPacket.data, receivedPacket.len-8);
ack_packet ackPacket{};
ackPacket.chsum= (0);
ackPacket.ackno= (receivedPacket.seqno);
ackPacket.len = (6);
sendto(sock, &ackPacket, 6,
0, &temp, sz);
if(receivedPacket.finished == 1)
break;
}
s
is the variable that tells me in the client how many bytes are received.
I suspected the write function in the ofstream
to be ignoring some of the write operations, maybe because it has some sort of internal buffer that was filled during some of the receives. However, I think that this is not right.
The issue was I don't close the file. Once it was closed data was written right. Alhamdullilah this was the problem