WinSocket如何处理一个典型的数据请求

Let’s   look   at   how   the   system   handles   a   typical   send   call   when   the   send   buffer   size   is   non-zero.   When   an   application   makes   a   send   call,   if   there   is   sufficient   buffer   space,   the   data   is   copied   into   the   socket’s   send   buffers,   the   call   completes   immediately   with   success,   and   the   completion   is   posted.   On   the   other   hand,   if   the   socket’s   send   buffer   is   full,   then   the   application’s   send   buffer   is   locked   and   the   send   call   fails   with   WSA_IO_PENDING.   After   the   data   in   the   send   buffer   is   processed   (for   example,   handed   down   to   TCP   for   processing),   then   Winsock   will   process   the   locked   buffer   directly.   That   is,   the   data   is   handed   directly   to   TCP   from   the   application’s   buffer   and   the   socket’s   send   buffer   is   completely   bypassed.  
The   opposite   is   true   for   receiving   data.   When   an   overlapped   receive   call   is   performed,   if   data   has   already   been   received   on   the   connection,   it   will   be   buffered   in   the   socket’s   receive   buffer.   This   data   will   be   copied   directly   into   the   application’s   buffer   (as   much   as   will   fit),   the   receive   call   returns   success,   and   a   completion   is   posted.   However,   if   the   socket’s   receive   buffer   is   empty,   when   the   overlapped   receive   call   is   made,   the   application’s   buffer   is   locked   and   the   call   fails   with   WSA_IO_PENDING.   Once   data   arrives   on   the   connection,   it   will   be   copied   directly   into   the   application’s   buffer,   bypassing   the   socket’s   receive   buffer   altogether.  
Setting   the   per-socket   buffers   to   zero   generally   will   not   increase   performance   because   the   extra   memory   copy   can   be   avoided   as   long   as   there   are   always   enough   overlapped   send   and   receive   operations   posted.   Disabling   the   socket’s   send   buffer   has   less   of   a   performance   impact   than   disabling   the   receive   buffer   because   the   application’s   send   buffer   will   always   be   locked   until   it   can   be   passed   down   to   TCP   for   processing.   However,   if   the   receive   buffer   is   set   to   zero   and   there   are   no   outstanding   overlapped   receive   calls,   any   incoming   data   can   be   buffered   only   at   the   TCP   level.   The   TCP   driver   will   buffer   only   up   to   the   receive   window   size,   which   is   17   KB—TCP   will   increase   these   buffers   as   needed   to   this   limit;   normally   the   buffers   are   much   smaller.   These   TCP   buffers   (one   per   connection)   are   allocated   out   of   non-paged   pool,   which   means   if   the   server   has   1000   connections   and   no   receives   posted   at   all,   17   MB   of   the   non-   paged   pool   will   be   consumed!   The   non-paged   pool   is   a   limited   resource,   and   unless   the   server   can   guarantee   there   are   always   receives   posted   for   a   connection,   the   per-socket   receive   buffer   should   be   left   intact.  
Only   in   a   few   specific   cases   will   leaving   the   receive   buffer   intact   lead   to   decreased   performance.   Consider   the   situation   in   which   a   server   handles   many   thousands   of   connections   and   cannot   have   a   receive   posted   on   each   connection   (this   can   become   very   expensive,   as   you’ll   see   in   the   next   section).   In   addition,   the   clients   send   data   sporadically.   Incoming   data   will   be   buffered   in   the   per-socket   receive   buffer   and   when   the   server   does   issue   an   overlapped   receive,   it   is   performing   unnecessary   work.   The   overlapped   operation   issues   an   I/O   request   packet   (IRP)   that   completes,   immediately   after   which   notification   is   sent   to   the   completion   port.   In   this   case,   the   server   cannot   keep   enough   receives   posted,   so   it   is   better   off   performing   simple   non-blocking   receive   calls.  

你可能感兴趣的:(socket,UP,performance)