// The first package of a packet sending process is the heartbeat package of the client. Now we have added a version package to check the package packaging process. The process persists, but it is hard to understand void NGP :: onlivetimer () // client heartbeat, send once every 5s {sendcmd (c2s_on_live, null, 0);} bool NGP: sendcmd (INT ncmd, void * pdata, int nlen) {// STD: wstring MSG = l "sending command:"; // MSG + = boost: lexical_cast <STD: wstring> (CMD ); // m_share-> log (MSG. c_str (); // sends the request for obtaining the game list protocol RPT = {0}; Rpt. performance_type = ncmd; Rpt. content = pdata; Rpt. size = nlen; STD: vector <char> buffer; Buffer. resize (nlen + sizeof (Protocol); // This length is personally acceptable-sizeof (void *). This position is actually overwritten int send_len = Rpt. to_buffer (& buffer [0], buffer. size (); For (;) {bool B = m_sptcplink-> send (& buffer [0], send_len); If (B) break; STD: this_thread :: sleep_for (STD: chrono: milliseconds (5);} return true;} // package format (this is the format of the initial packet sending)-(one byte Protocol) ---- (the length of four bytes indicates the size of the subsequent content) --------------- (Package content) struct Protocol {unsigned char pai_type; Int size; // content length, excluding the void * Content Header of this Protocol; int to_buffer (void * buffer, int buffer_len) // {If (! Buffer) Return-1; int total_size = size + sizeof (Protocol)-sizeof (void *); //-sizeof (void *) it is because if (buffer_len <total_size) that is copied from the pointer position is the provided memory size, and total_size is the total size after packaging. Return-1; protocol * P = (Protocol *) buffer; // regard the memory model as the protocol model P-> protocol _type = This-> protocol _type; P-> size = This-> size; if (content) {memcpy (& P-> content, content, size); // copy the content from the beginning of the pointer} return total_size ;}} // This package has another one in libevent Packaging Process ---- (4 bytes, indicating the total length of the backbread)-(one-byte protocol) ---- (the length of the four bytes indicates the size of the subsequent content) ----------------- (Package content) therefore, the length of the heartbeat packet is 9 bytes. // The read event of the process thread that the server receives is called/* read data stream */void channel :: read_datastream (struct bufferevent * BEV) {// bufferevent_read reads the data in the input buffer each time. It seems that up to 4096 bytes can be read. Therefore, such a large amount of data may be multiple packages, another possibility is that none of the packages will be available. This is a problem: size_t Len = bufferevent_read (BEV, m_buf, sizeof (m_buf);/*** [test]: Unlock first and lock again, prevent the send_data of main_thread from being blocked when the thread waits for an endless loop when memory allocation fails. */Evbuffer_unlock (Bev-> output); // Auto & in = Bev-> input; same as lock // Auto & out = Bev-> output; m_readstream.push (m_buf, len); // datastream is equivalent to a buffer. In this process, I understand the waste, and finally I learned about read_pack () with the help of both (); evbuffer_lock (Bev-> output);} void push (const void * pbuf, int nlen) {char * pbuf2 = (char *) pbuf; m_streambuffer.insert (m_streambuffer.end (), pbuf2, pbuf2 + nlen); // Insert the package to the last position each time}/* read package */void channel: read_pack () {If (m_readstream.size () <4) // If the size is smaller than 4, it indicates that the read is finished, and there cannot be a packet smaller than 4 bytes. It may be an incomplete package return; size_t Len = * (size_t *) m_readstream.peek (); // obtain the first four bytes, indicating the length of the Package content. If (m_readstream.size () <4 + Len) // indicates that the package does not comply with the rules. It should >=, of course, it may also be because this package is incomplete. Wait for the next time to parse return; m_event-> on_receive_data (m_id, m_readstream.peek () + 4, Len ); // process the package m_readstream.pop (4 + Len); // each package escaped from the next read location read_pack (); // until it has been read} void POP (INT nlen) {m_head_size + = nlen; // move the header flag if (m_head_size> m_buff_len) {// This array can be used as a cyclic queue, there is also a way to use cyclic queue: Two cursors: m_streambuffer.erase (m_streambuffer.begin (), m_streambuffer.begin () + m_head_size); // Delete and reserve again, which may prevent reading errors, not clear: m_head_size = 0; m_streambuffer.reserve (m_buff_len );}}
There are still many things to do about the final arrival of Gs. We can analyze this for the time being.
Libevent process of one package