I get the packages by upd and create the structure PSG. Then I save it to a vector and sort.At the end, I write all the byte data to a file. The problem is that the last packet is less than 1424 bytes. and because of this, extra bytes are written to the end of the file. How could I correctly save data from recvfrom() to a structure to avoid extra bytes?
#pragma pack(push, 1)
struct PSG
{
uint64_t id;
uint64_t size;
uint32_t type;
uint32_t count;
uint8_t data[1400];
};
#pragma pack(pop)
PSG psg;
std::vector<PSG> psg_vector;
while(1) {
if ((bytesrecv = recvfrom(m_sock, &psg, 1424, 0, (sockaddr *) NULL, NULL)) < 0) {
perror("recvfrom");
close(m_sock);
return -1;
}
psg_vector.push_back(psg);
sort(psg_vector.begin(), psg_vector.end(), [](const auto &lhs, const
auto &rhs) {
return lhs.count < rhs.count;
});
for (auto &a: psg_vector) {
file.write(reinterpret_cast<const char *>(&a.data), sizeof(a.data));
}
}
CodePudding user response:
Example on linux sockets. You need this lines:
if (!length) // Write entire buffer
fileManager.WriteFile(data->buffer, BUFF_LENGTH);
else // Write remain
{
fileManager.WriteFile(data->buffer, length);
break;
}
Full example:
struct Packet
{
enum class TYPE
{
DEFAULT = 3, // Default condition
LAST_OF_FILE = 4, // Last packet of file
N_LAST_OF_FILE = 5, // Not last packet of file
LAST_IN_GROUP = 6, // Last file in group of files, sent by client
N_LAST_IN_GROUP = 7, // Not last file in group of files, sent by client
ANSWER = 8 // Answer
};
uint32_t length;
TYPE type;
char buffer[BUFF_LENGTH];
void clear()
{
memset(this, 0, sizeof(Packet));
}
};
bool ReceiveOnePacket(Packet* pack, int* socket)
{
// summary quantity of received bytes
uint32_t bytes = 0;
while (bytes < sizeof(Packet))
{
// a tcp socket cannot give the entire packet as a whole, so we read it in parts.
// We read with a shift and reduce the number of remaining bytes
int len = recv(*socket, ((char*)pack) bytes, sizeof(Packet) - bytes, 0);
if (len <= 0)
return false;
bytes = len;
}
return true;
}
void ReceivingFiles(std::shared_ptr<int> socket, std::shared_ptr<Packet> data)
{
data->clear();
bool isLastFile = false;
while (!isLastFile) // Receiving set of files
{
// receiving filename of current file
if (!ReceiveOnePacket(data.get(), socket.get()))
{
close(*socket);
return;
}
// if current file is last then data->packetType == Packet::TYPE::LAST_IN_GROUP,
// if file not last, data->packetType == Packet::TYPE::N_LAST_IN_GROUP
isLastFile = data->type == Packet::TYPE::LAST_IN_GROUP;
std::string metaData(data->buffer, data->length);
fileManager.OpenFile(metaData);
// Receiving one File
while (true)
{
if (!ReceiveOnePacket(data.get(), socket.get()))
{
fileManager.DeleteFile();
close(*socket);
return;
}
uint32_t length = data->length;
if (!length) // Write entire buffer
fileManager.WriteFile(data->buffer, BUFF_LENGTH);
else // Write remain
{
fileManager.WriteFile(data->buffer, length);
break;
}
} // End Receiving one file
}
}
CodePudding user response:
You're getting the size of the packet read in bytesrecv, but then you're ignoring it and not using it. Store it somewher and use it. You could add it to your PSG object:
#pragma pack(push, 1)
struct PSG
{
uint64_t id;
uint64_t size;
uint32_t type;
uint32_t count;
uint8_t data[1400];
ssize_t size;
};
#pragma pack(pop)
PSG psg;
std::vector<PSG> psg_vector;
while(1) {
if ((psg.size = recvfrom(m_sock, &psg, 1424, 0, (sockaddr *) NULL, NULL)) < 0) {
perror("recvfrom");
close(m_sock);
return -1;
}
psg_vector.push_back(psg);
