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);