Как сохранить чтение границы сообщения TCP - PullRequest
0 голосов
/ 27 марта 2019

Я пытаюсь написать программу клиент-сервер tcp для связи, ориентированной на сообщения.размер моего сообщения всегда составляет 1040 байт с включенным 16-байтовым заголовком.

Ниже приведен фрагмент кода.

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

случайным образом, то есть иногда после 1000 сообщений или иногда 30000 сообщений внезапно я получаю очень большую длину полезной нагрузки, и чтение полностью прекращается.

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
...