c - Handling multiple recv() calls and all possible scenarios -


i new c , writing tcp server, , wondering how handle recv()'s client send commands server respond to. sake of question, let's header 1st byte, command identifier 2nd byte, , payload length 3rd byte, followed payload (if any).

what best way recv() data? thinking call recv() read in first 3 bytes buffer, check make sure header , command identifiers valid, check payload length , call recv() again payload length length , add of aforementioned buffer. reading beej's networking article (particularly section here: http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#sonofdataencap), however, advises use "an array big enough 2 [max length] packets" handle situations such getting of next packet.

what best way handle these types of recv()'s? basic question, implement efficiently, handling cases can arise. in advance.

the method beej alluding to, , alastairg mentions, works this:

for each concurrent connection, maintain buffer of read-but-not-yet-processed data. (this buffer beej suggests sizing twice maximum packet length). obviously, buffer starts off empty:

unsigned char recv_buffer[buf_size]; size_t recv_len = 0; 

whenever socket readable, read remaining space in buffer, try , process have:

result = recv(sock, recv_buffer + recv_len, buf_size - recv_len, 0);  if (result > 0) {     recv_len += result;     process_buffer(recv_buffer, &recv_len); } 

the process_buffer() try , process data in buffer packet. if buffer doesn't contain full packet yet, returns - otherwise, processes data , removes buffer. example protocol, like:

void process_buffer(unsigned char *buffer, size_t *len) {     while (*len >= 3) {         /* have @ least 3 bytes, have payload length */          unsigned payload_len = buffer[2];          if (*len < 3 + payload_len) {             /* short - haven't recieved whole payload yet */             break;         }          /* ok - execute command */         do_command(buffer[0], buffer[1], payload_len, &buffer[3]);          /* shuffle remaining data in buffer start */         *len -= 3 + payload_len;         if (*len > 0)             memmove(buffer, buffer + 3 + payload_len, *len);     } } 

(the do_command() function check valid header , command byte).

this kind of technique ends being necessary, because any recv() can return short length - proposed method, happens if payload length 500, next recv() returns 400 bytes? you'll have save 400 bytes until next time socket becomes readable anyway.

when handle multiple concurrent clients, have 1 recv_buffer , recv_len per client, , stuff them per-client struct (which contains other things - client's socket, perhaps source address, current state etc.).


Comments

Popular posts from this blog

asp.net - repeatedly call AddImageUrl(url) to assemble pdf document -

java - Android recognize cell phone with keyboard or not? -

iphone - How would you achieve a LED Scrolling effect? -