Home > Mobile >  Save data from `recvfrom()` to a structure to avoid extra bytes?
Save data from `recvfrom()` to a structure to avoid extra bytes?

Time:10-07

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);
  •  Tags:  
  • c
  • Related