Implementation Based on socket simple communication protocol

Source: Internet
Author: User
Scenario 1

When a socket is used for process communication and data transmission, the following situations may occur:

(1) The system splits a complete message into several messages for sending. For example, if you want to send a message: Hello world, it is divided into two messages for sending: Hello and world.

(2) several independent messages are sent by a system synthesis message. For example, to send two messages: a memory from my past and it's been a year, sent by the system and a message: a memory from my pastit's been a year.

In this case, we need to design a communication protocol for socket communication to ensure data accuracy.

2 protocol format

The communication protocol is designed as follows:


Head: The frame header, two bytes. 0xa5a5 is used here.

Type: Communication type, 1 byte, range: 0x00 ~ 0xff

Data Length: Data Length, 1 byte, that is, the total number of data bytes,

Data: The actual transmitted data, with an indefinite length

CS: Check value, 1 byte, type, data length, and data all the bytes of the same or value. Verification is not used in reality.

End: The end of the frame, two bytes. The value is 0 xbeef.

 

3 Program Design
3.1 parsing ideas

Assume that Socket Client C communicates with server s, and C sends message M1 to S.

1. s receives the message M1. S copies the message M1 to the cache Q, and Q is a cyclic queue. If the length of M1 is greater than the remaining space of Q, only the bytes of the remaining space are copied to Q.

2. Search for the frame header

3. Search for <type> from the current pointer of Q. If at least one byte is left in Q, it indicates it is found. The current pointer is shifted to the next byte; otherwise, resolution is exited.

4. Search for <datalength> from the current pointer of Q. If at least one byte is left in Q, it indicates it is found. The current pointer is shifted to the next byte; otherwise, resolution is exited.

5. Start from the current pointer of Q and move datalength byte to the back to find <End>. If this parameter is found, a complete message P1 is extracted from Q, the message space is deleted from Q, and an external callback function is called. Otherwise, the first byte A5 of the frame header is deleted, the current Pointer Points to the second A5 position in the frame header, starting from step 2 and re-parsing.

 

3.2 Data Structure

Search Policy Enumeration, used to determine the location of the frame structure during search:

typedef enum{SEARCH_HEAD,SEARCH_TYPE,SEARCH_LEN,//SEARCH_CS,SEARCH_END,SEARCH_NONE}cache_strategy;

Message struct, used to store parsed data from the cache:

typedef struct{unsigned char data[SOCKET_MSG_SIZE];//dataint len;unsigned char type;}socket_msg;

The callback function is called when a message is parsed from the cache:

typedef void (*tp_socket_msg_handle)(int fd, socket_msg *msg,void *args);

Cyclic queue, used to cache received data:

typedef struct{unsigned char buf[SOCKET_MSG_CACHE_SIZE]; //buffer for storing data read from clientint front;int rear;int current;int len;int tag;//mark that whether the cache is full,1-full,0-not fullcache_strategy strategy;tp_socket_msg_handle handle;//callback function to invoke when a message is parsed outvoid* args;//external parametersocket_msg recv_msg;//parsed message}socket_cache;

3.3 key implementation

1. Store the received data in the buffer and prepare for parsing:

//copy the unparsed data to cache, and parsed themint socket_msg_pre_parse(int fd, socket_cache *cache,unsigned char *buf, int len, void *args){int n = 0;unsigned char *p = buf;//when reading buffer's length is greater than cache's left length,//we should copy many times.cache->args = args;while(1){n = socket_msg_cpy_in(cache, p, len);if(n == 0){return FALSE;//cache is full}//parse and handle socket message from cachesocket_msg_parse(fd, cache);if(n == len){return TRUE; //copy completed}//move the pointerp = p + n;len = len - n;}return TRUE;}

2. parse messages recursively:

//parsed the packaged data, and invoke callback functionvoid socket_msg_parse(int fd, socket_cache *cache){int current_len;int p, q;int i;int find;if(cache->front == cache->rear && cache->tag == 0){//D("socket cache is empty!\n");return;}//calculate the current length of cacheif(cache->current >= cache->front){current_len = cache->len - (cache->current - cache->front);}else{current_len = cache->rear - cache->current;}switch(cache->strategy){case SEARCH_HEAD://to find a Head format in cacheif(current_len < SOCKET_MSG_HEAD_SIZE){return;}find = FALSE;for(i = 0; i < current_len - 1; i++){p = cache->current;q = (cache->current + 1) % SOCKET_MSG_CACHE_SIZE;if((cache->buf[p] == (SOCKET_MSG_HEAD >> 8))&&(cache->buf[q] == (SOCKET_MSG_HEAD & 0xff))){find = TRUE;break; //exit for loop}else{//current pointer move to nextcache->current = q;//delete one itemcache->front = cache->current;cache->len --;cache->tag = 0;}}if(find == TRUE){//move 2 items towards nextcache->current = (cache->current + 2) % SOCKET_MSG_CACHE_SIZE;//we found the head format, go on to find Type bytecache->strategy = SEARCH_TYPE;}else{//if there is no head format ,delete previouse itemsLOGE("socket message without head: %x!\n",SOCKET_MSG_HEAD);//go on to find Head formatcache->strategy = SEARCH_HEAD;}break;case SEARCH_TYPE://to find the type byte in cacheif(current_len < SOCKET_MSG_TYPE_SIZE){return ;}//get the value of type//cache->type = cache->buf[cache->current];cache->recv_msg.type = cache->buf[cache->current];cache->current = (cache->current + 1) % SOCKET_MSG_CACHE_SIZE;//we found Type byte, go on to find Datalen formatcache->strategy = SEARCH_LEN;break;case SEARCH_LEN://to find the datalen byte in cacheif(current_len < SOCKET_MSG_LEN_SIZE){return ;}if(cache->buf[cache->current] > SOCKET_MSG_DATA_SIZE){LOGE("the data len of message out of size: %d!\n",SOCKET_MSG_DATA_SIZE);//delete the frist item 'a5'//move back 2 itemscache->current = cache->current >= 2 ? (cache->current - 2) : (SOCKET_MSG_CACHE_SIZE - 2 + cache->current);cache->front = cache->current;//length sub 2cache->len -= 2;cache->tag = 0;//go on to find Head formatcache->strategy = SEARCH_HEAD;}else{//get the value of datalen//cache->data_len = cache->buf[cache->current];cache->recv_msg.len = cache->buf[cache->current];cache->current = (cache->current + 1) % SOCKET_MSG_CACHE_SIZE;//we found datalen byte, go on to find End formatcache->strategy = SEARCH_END;}break;case SEARCH_END:if(current_len < (cache->recv_msg.len + SOCKET_MSG_END_SIZE)){return;}//because we have known the data bytes' len, so we move the very  //distance of datalen to see if there is End format. p = (cache->current + cache->recv_msg.len) % SOCKET_MSG_CACHE_SIZE; q = (cache->current + cache->recv_msg.len + 1) % SOCKET_MSG_CACHE_SIZE; if((cache->buf[p] == (SOCKET_MSG_END >> 8))&&(cache->buf[q] == (SOCKET_MSG_END & 0xff)) ){socket_msg_cpy_out(cache, cache->recv_msg.data, cache->current, cache->recv_msg.len);if(cache->handle != NULL){//cache->handle(fd, cache->buf + cache->data_index, cache->data_len);cache->handle(fd, &cache->recv_msg, cache->args);}//delete all previous itemscache->current = (q + 1) % SOCKET_MSG_CACHE_SIZE;cache->front = cache->current;cache->len -= (cache->recv_msg.len + SOCKET_MSG_FORMAT_SIZE);cache->tag =0;}else{LOGE("socket message without end: %x!\n",SOCKET_MSG_END);//delete the frist item 'a5'//move back 3 itemscache->current = cache->current >= 3 ? (cache->current - 3) : (SOCKET_MSG_CACHE_SIZE - 3 + cache->current);cache->front = cache->current;//length sub 3cache->len -= 3;cache->tag = 0;}//go on to find Head formatcache->strategy = SEARCH_HEAD;break;default:break;}//parse new socket messagesocket_msg_parse(fd,cache);}



















































































Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.