Note that there are some explanatory texts on larger screens.

plurals
  1. POProblems parsing a TCP-based TLV protocol in C++
    primarykey
    data
    text
    <p>I am trying to implement a (T)LV protocol over TCP sending protocol buffers from a python client and receiving with a C++ server.</p> <p>My code looks more or less like this:</p> <pre><code>char* buffer[RCVBUFSIZE]; int recvsize= 0; // Filling my buffer with as much as possible. while(true) { if(recvsize == RCVBUFSIZE) { break; } else if(recvsize+= recv(sock, buffer+recvsize, sizeof(buffer)-recvsize, 0) &lt; 1) { break; } } //Parsing LV protocol while(true) { unsigned short protosize= 0; //Copy first two bytes into protosize memcpy((char *) &amp;protosize, buffer, sizeof(unsigned short)); if(protosize == 0) { break; } // Protocol indicates EOM be setting length to "0" void* protomsg[protosize]; memcpy(protomsg, buffer+sizeof(unsigned short), protosize); int msglength= sizeof(unsigned short)+protosize; //Now I'll move the whole buffer to the left so that I don't have to keep track of where I'm at. memmove(buffer, buffer+msglength, RCVBUFSIZE-msglength); protoMsg pm; if(!pm.ParseFromArray(protomsg, protosize)) { break; } // Parsing failed. // Do stuff with parsed message. } </code></pre> <p>Now I have several problems:</p> <ul> <li>The while loop receiving the message never terminates. I suspect that the recv call blocks when there isn't any data left anymore while I expected it to return with an error. I have found the select function to check whether there's something to read. I will give that a try. But when I call receive only once to skip this problem (The message received comes in at ~10 bytes, so I expect all to be collected in one call.) I get another problem:</li> <li>memcpy and memmove don't seem to be working as expected. On the first loop the short is processed as expected (I receive the same value I send on the other side), but then everything from parsing of the protocol buffer fails. Have I misunderstood something?</li> </ul> <p><strong>Edit:</strong> Regarding the comment about ntohs -- I'm transmitting the short as little-endian currently, forgot to mention that. (I will change this still, btw.)</p> <p><strong>Third edit:</strong> The code now works, but I had to change the following:</p> <pre><code>char* buffer[RCVBUFSIZE]; int recvsize= 0; // Filling my buffer with as much as possible. while(true) { if(recvsize == RCVBUFSIZE) { break; } else if((recvsize+= recv(sock, buffer+recvsize, sizeof(buffer)-recvsize, 0)) &lt; 1) { break; } else if(recvsize &gt; 1) { unsigned short msglength= 0; memcpy((char *) &amp;msglength, buffer+recvsize-sizeof(unsigned short), sizeof(unsigned short)); if(msglength == 0) { break; } // Received a full transmission. } } </code></pre> <p>So first I needed to add brackets around the <code>recvsize+= recv()</code> statement and second as the non-blocking method didn't work for some reason I am now checking whether the last two bytes that were transmitted translate to a 0 when read a unsigned short. This probably leads to a problem if I read a 0 by chance that is not the length field. I'll start another question about this probably.</p> <p>I also changed <code>protomsg</code> to <code>char[]</code>, but I don't think this really changed anything. (I had parsing working with a void array already.. )</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload