mercredi 27 mars 2019

How to preserve TCP message boundary reading

i am trying to write tcp client server program to have message oriented communication. my message size is always 1040 bytes with 16 bytes header included.

following is the code snippet.

class connection
{
....

#define BUFFER_SIZE 65535

        uint8_t buffer[BUFFER_SIZE + BUFFER_SIZE];
        std::size_t rem_buff = BUFFER_SIZE;
        std::size_t avail_size = 0;
        uint8_t *buffer_write = buffer;
        uint8_t *buffer_reader = buffer;
        Header mh;
        long count = 0;

        bool read_header = true;
};

void connection::read()
{
    bool conn_terminated = false;
    std::size_t read_bytes = 0;

    if (rem_buff > 0) {
        assert((buffer_write + rem_buff) <= (buffer + BUFFER_SIZE));
        assert(buffer_write >= buffer_reader);
        read_bytes = utils::read(handle(), buffer_write, rem_buff, conn_terminated, false);
        if (read_bytes > 0) {
            rem_buff -= read_bytes;
            buffer_write += read_bytes;
            avail_size = buffer_write - buffer_reader;
            std::cout << "read_bytes : " << read_bytes
                << " avail_size : " << avail_size << ", rem_buff : " << rem_buff << std::endl;
        } else if (conn_terminated) {
            std::cout << "connection terminated" << std::endl;
            return;
        }
        if (avail_size < 1) {
            return;
        }
    }
    do {
        if (read_header) {
            if (avail_size > sizeof(Header)) {
                // header is ready
                read_header = false;
                mh = *(reinterpret_cast<Header*>(buffer_reader));

                buffer_reader += sizeof(Header);
                avail_size -= sizeof(Header);
                std::cout << "payload : " << mh.length()
                    << ", avail_size : " << avail_size
                    << std::endl;
                if (mh.length() > 1024) {
                    std::cout << "count : " << count << std::endl;
                }
            } else if (rem_buff == 0) {
                // there is no space left to read complete header
                memmove(buffer, buffer_reader, avail_size);

                // reinit all pointers
                buffer_reader = buffer;
                buffer_write = buffer_reader + avail_size;
                rem_buff = BUFFER_SIZE - avail_size;
                std::cout << "move1: avail_size : " << avail_size << ", rem_buff : " << rem_buff << std::endl;
                break;
            } else {
                // header is not complete
                break;
            }
        }

        if (!read_header) {
            if (avail_size >= mh.length()) {
                ++count;
                buffer_reader += mh.length();
                avail_size -= mh.length();
                read_header = true;
            } else if (avail_size < mh.length()) {
                // TODO: still not handling partial payload read
                if (rem_buff == 0) {
                    // there is no space left to read complete header
                    memmove(buffer, buffer_reader, avail_size);

                    // reinit all pointers
                    buffer_reader = buffer;
                    buffer_write = buffer_reader + avail_size;
                    rem_buff = BUFFER_SIZE - avail_size;
                    std::cout << "move2: avail_size : " << avail_size << ", rem_buff : " << rem_buff << std::endl;
                }
                break;
            }
        }
    } while (avail_size > 0);
}

randomly, that is, sometimes after 1000 messages or sometimes 30000 messages suddenly i get a very huge payload length and reading completely stops.

payload : 1024, avail_size : 1039
move1: avail_size : 15, rem_buff : 65520
read_bytes : 6225 avail_size : 6240, rem_buff : 59295
payload : 45680032226158504, avail_size : 6224

Aucun commentaire:

Enregistrer un commentaire