2016-04-06 3 views
2

У меня реализовать сокет связи, как следующее:вопрос производительности RECV в C

Гнездо Клиент посылает «0010ABCDEFGHIJ» на сервер сокета, первые 4 байта (в данном случае, «0010») описывают тело сообщения имеет 10 байтов, и последующие байты - это тело сообщения !!

Я использую «The Linux Programming Interface» readn функции в стороне сервера, источник:

ssize_t 
readnx(int fd, void *buffer, size_t n) 
{ 
    ssize_t numRead;     /* # of bytes fetched by last read() */ 
    size_t totRead;      /* Total # of bytes read so far */ 
    char *buf; 

    buf = (char*) buffer;    /* No pointer arithmetic on "void *" */ 
    for (totRead = 0; totRead < n;) { 
     numRead = recv(fd, buf, n - totRead,MSG_NOSIGNAL); 

     if (numRead == 0)    /* EOF */ 
      return totRead;    /* May be 0 if this is first read() */ 
     if (numRead == -1) { 
      if (errno == EINTR) 
       continue;    /* Interrupted --> restart read() */ 
      else 
       return -1;    /* Some other error */ 
     } 
     totRead += numRead; 
     buf += numRead; 
    } 
    return totRead;      /* Must be 'n' bytes if we get here */ 
} 


void *thread1(void *param) 
{ 
    int nread = 0 ; 
    char strdata[1024]={0},strtmp[128]={0} ; 
    pthread_detach(pthread_self()); 
    while(1) 
    { 
     memset(strtmp,0x00,sizeof(strtmp)) ; 
     if ((nread = readnx(sd,strtmp,4)) <= 0){ 
      break ; 
     } 
     int ilen = atoi(strtmp) ; 
     memset(strdata,0x00,sizeof(strdata)) ; 
     if ((nread = readnx(sd,strdata,ilen)) <= 0){ 
      break ; 
     } 
    }//while 
} 

Это прекрасно работает для меня, я хотел бы узнать более подробную информацию о производительности, У меня есть функция 2 readnx вызовы в моем исходном коде и выполнение этого в режиме блокировки. Если я изменил свой код, чтобы сначала сделать recv с MSG_PEEK, после того, как все 14 байтов будут доступны, затем вызовите readnx один раз, чтобы получить все данные, Будет ли это быстрее, чем мои оригинальные 2 вызова readnx?!

мне интересно, в моем оригинальном источнике, у меня есть 2 readnx к ПРИЕМУ «0010» и «ABCDEFGHIJ» отдельно, будет ли это причина ядра Linux для копирования пользовательского пространства в два раза даже все 14 байт, все там уже на время I называется первым readnx?! Или ядро ​​копирует все 14 байтов в пространство пользователя только один раз, функция readnx просто считывает его из пользовательского пространства?!

Если мне нравится знать эти сведения о процедурах пространства ядра для пользователя, какие документы, вызов функции могут помочь мне просмотреть детали.

+0

удалить C++ tag now .. исправить ошибку. – barfatchen

+0

Btw, так как вы заинтересованы в сокращении накладных расходов, вы можете избавиться от этих вызовов memset(), поскольку recv() будет немедленно перезаписывать эти же байты в любом случае. Нет смысла переписывать их дважды. (Вам нужно будет написать один байт NUL-терминатора в позиции nread'th, чтобы строка NUL была завершена, так что atoi() будет работать правильно) –

+0

Количество вызовов recv() на сообщение может быть уменьшено до 1 (или меньше), всегда считывая как можно больше байтов для каждого вызова (в большой массив), а затем анализируя как можно больше байтов из этого массива и сохраняя остальное на потом.Недостатком является то, что логика состояния, необходимая для этого, довольно сложна и сложна, чтобы получить право во всех случаях, и я был бы удивлен, если бы вы видели какую-либо измеримую разницу в производительности, если только ваш входящий поток данных (например, сотни мегабайт в секунду), или ваш процессор работает очень медленно. –

ответ

2

Если я изменить код, чтобы сделать ПРИЕМ с MSG_PEEK первым после того, как все 14 байт все имеющиеся

Это означает, что вы собираетесь спать и повторите попытку. Как долго вы собираетесь спать? Откуда вы знаете, как далеко друг от друга будут собираться куски?

затем вызов readnx один раз для получения всех данных, будет ли он быстрее, чем мои оригинальные 2 вызова readnx?

Нет. Вы не будете спать в течение правильного времени, в отличие от recv(), и вы можете сделать намного больше, чем один MSG_PEEK.

Если вы беспокоитесь о производительности двух recv() вызовов, или сколько он принимает, вы должны сделать все возможное в отправителе обеспечить заголовок и сообщение отправляются в то же время: есть посмотрите на sendmsg().

Смежные вопросы