recv 数据包形式 效率比拼

recv 数据包形式 效率比拼_开心镇娱乐社区_百度空间

recv 数据包形式 效率比拼

由于tcp是流协议,但实际中使用数据包协议比较多,所以应用层需要自己包装一个

void client_thread(tp_work*this, tp_work_desc*job) {
int connectID = (int) job->chnum;
free(job);
char left_buf[MSG_RECV_LEN]="0";
int left_len = 0;
int res;
int i;
char rbuf[MSG_RECV_LEN];
while(1){
   memset(rbuf,'\0',MSG_RECV_LEN);
   res = recv(connectID, rbuf, MSG_RECV_LEN,0);
   if (res < 0) {
    close(connectID);
    break ;
   } else if (0 == res) {
    close(connectID);
    break ;
   } else {
    for(i = 0;i < res;i++){
     if(rbuf[i] == '\0'){ //分割符  
      left_buf[left_len] = '\0';  
      msg_recv_queue_put(g_pRMsg, connectID,left_buf,left_len+1);
      left_len = 0;
      continue;
     }
     else {
      left_buf[left_len] = rbuf[i];
      left_len ++;
     }
     if(left_len == MSG_RECV_LEN){
      left_len = 0;
     }    
    }
   }
}
}

这个代码简介,结构清晰

void client_thread(tp_work*this, tp_work_desc*job) {
int connectID = (int) job->chnum;
free(job);
char left_buf[MSG_RECV_LEN]="0";
int left_len = 0;
int res;
char rbuf[MSG_RECV_LEN];
int pro_len;
char *pos;
char *pCur;
while(1){
   res = recv(connectID, rbuf, MSG_RECV_LEN,0);
   pCur = rbuf;
   if (res < 0) {
    close(connectID);
    break ;
   } else if (0 == res) {
    close(connectID);
    break ;
   } else {
    while(res > 0&&(pos = memchr(pCur,'\0',res)) != 0){//是否含有 分隔符
     pro_len = pos - pCur+1;
     if(left_len+pro_len <= MSG_RECV_LEN){//超过最大长度
      memcpy(left_buf+left_len,pCur,pro_len);
      msg_recv_queue_put(g_pRMsg, connectID,left_buf,left_len+pro_len);     
     }
     left_len = 0;
     pCur = pCur + pro_len;
     res = res -pro_len;
    }
    if(left_len + res >= MSG_RECV_LEN){
     left_len = 0;
     continue;
    }
    memcpy(left_buf+left_len,pCur,res);
    left_len += res;   
   }
}
}

这个代码稍微有点晦涩,调用系统的string库函数查找分割符

经过测试在不优化编译的情况下第二种代码是第一种的7-10倍

由此得出string库的函数是经过优化的,速度很快,memcpy memstr 效率很高

/* Search no more than N bytes of S for C. */
//若成功则返回字符在缓冲区的位置,否则返回NULL
//原型为
//void *memchr( const void *buf, int c, size_t count )
__ptr_t     //就是void*
__memchr (s, c_in, n)
     const __ptr_t s;    //缓冲区指针
     int c_in;           //要查找的字符
     size_t n;           //要检查的字符数
{
const unsigned char *char_ptr;
const unsigned long int *longword_ptr;
unsigned long int longword, magic_bits, charmask;
unsigned reg_char c; //这里reg_char可以认为是char

c = (unsigned char) c_in;

/* Handle the first few characters by reading one character at a time.
     Do this until CHAR_PTR is aligned on a longword boundary. */
for (char_ptr = (const unsigned char *) s;
       n > 0 && ((unsigned long int) char_ptr    //char的size是1,unsigned long int的size 是4
         & (sizeof (longword) - 1)) != 0;//查找前几个字符,一直到可以与unsigned long int对齐的地方
       --n, ++char_ptr)                          //这时候如果没有查找到,char_ptr的地址已经可以被4整除了
    if (*char_ptr == c)
      return (__ptr_t) char_ptr;

/* All these elucidatory comments refer to 4-byte longwords,
     but the theory applies equally well to 8-byte longwords. */

longword_ptr = (unsigned long int *) char_ptr;
//这里开始没有看懂,请高手指点
/* Bits 31, 24, 16, and 8 of this number are zero. Call these bits
     the "holes." Note that there is a hole just to the left of
     each byte, with an extra at the end:

     bits: 01111110 11111110 11111110 11111111
     bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD

     The 1-bits make sure that carries propagate to the next 0-bit.
     The 0-bits provide holes for carries to fall into. */

if (sizeof (longword) != 4 && sizeof (longword) != 8)
    abort ();

#if LONG_MAX <= LONG_MAX_32_BITS
magic_bits = 0x7efefeff;
#else
magic_bits = ((unsigned long int) 0x7efefefe << 32) | 0xfefefeff;
#endif

/* Set up a longword, each of whose bytes is C. */
charmask = c | (c << 8);
charmask |= charmask << 16;
#if LONG_MAX > LONG_MAX_32_BITS
charmask |= charmask << 32;
#endif

/* Instead of the traditional loop which tests each character,
     we will test a longword at a time. The tricky part is testing
     if *any of the four* bytes in the longword in question are zero. */
while (n >= sizeof (longword))
    {
      longword = *longword_ptr++ ^ charmask;

      /* Add MAGIC_BITS to LONGWORD. */
      if ((((longword + magic_bits)

        /* Set those bits that were unchanged by the addition. */
        ^ ~longword)

       /* Look at only the hole bits. If any of the hole bits
          are unchanged, most likely one of the bytes was a
          zero. */
       & ~magic_bits) != 0)
    {
      /* Which of the bytes was C? If none of them were, it was
         a misfire; continue the search. */

      const unsigned char *cp = (const unsigned char *) (longword_ptr - 1);

      if (cp[0] == c)
        return (__ptr_t) cp;
      if (cp[1] == c)
        return (__ptr_t) &cp[1];
      if (cp[2] == c)
        return (__ptr_t) &cp[2];
      if (cp[3] == c)
        return (__ptr_t) &cp[3];
#if LONG_MAX > 2147483647
      if (cp[4] == c)
        return (__ptr_t) &cp[4];
      if (cp[5] == c)
        return (__ptr_t) &cp[5];
      if (cp[6] == c)
        return (__ptr_t) &cp[6];
      if (cp[7] == c)
        return (__ptr_t) &cp[7];
#endif
    }

      n -= sizeof (longword);
    }

char_ptr = (const unsigned char *) longword_ptr;

while (n-- > 0)
    {
      if (*char_ptr == c)
    return (__ptr_t) char_ptr;
      else
    ++char_ptr;
    }

原文地址:https://www.cnblogs.com/lexus/p/3002861.html