如何保留TCP消息边界读取

时间:2019-03-27 18:47:34

标签: c++11 tcp centos7

我正在尝试编写tcp客户端服务器程序以进行面向消息的通信。我的邮件大小始终为1040字节,包括16字节的标头。

以下是代码段。

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea name="txtScript" id="my_word_count" cols="100" rows="10"></textarea>
<br>Total word Count : <span id="display_word_count">0</span> words.
<br><span id="display_word_count_message"></span>

随机地,也就是说,有时在1000条消息或30000条消息之后,我突然得到了非常长的有效载荷长度,并且读取完全停止。

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

0 个答案:

没有答案