Re: About zero-byte receive (IOCP server)



IMHO, while this approach will work, I would recommend against the use of
zero-byte receives in any IOCP server. This design is a signal and process
scheme that will perform badly for high data rates and be wastefully
inefficient in all circumstances except when hosting a very large number
(>10,000) connections that only rarely send anything (mass broadcast
application).



Most modern hardware has at least 1 GB of RAM so using 10-50 MB of it to
dramatically improve the IO efficiency only makes sense.


"George" <George@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
news:D5504096-7D6E-44B5-BA2F-B274FD0B1454@xxxxxxxxxxxxxxxx
You are right, nothing bad about using WSARescv () with overlapped
sockets.The problem is that on completion of a zero-byte receive IOCP
worker
threads should read complete data received.When using overlapped IO you
couldn't know whether you read all existing data or not. But if you
switch
the socket to non-blocking mode and then issue
non-overlapped,non-blocking
WSARecv () s in a loop, you can read all data present by testing return
value of WSAGetLastError () with WSAEWOULDBLOCK.Then you can issue
another
zero-byte receive for that socket.This seems reosanable to me because, in
this way, I exactly know when to post zero-byte receives.


On a zero-byte recv you don't have to read all the data, read whatever
your
buffer size is, then post another zero-byte recv, if there was any data
left
to be read then the completion pack will be scheduled to the IOCP.

However, you could also do what you suggest i.e. loop around recv(...)
until
it returns WSAEWOULDBLOCK, post another zero-byte recv and then process
the
current data. BUT BE CAREFUL, there is a potential of starving the
bandwidth
here, lets say the client has a high-speed connection, in this case the
client socket will be constantly sending in data and you could end up
spending a lot of time in recv-loop. One way to counter this is by setting
a
limit i.e. loop only 3 times or something along those lines - personally I
would go with 2-5 iterations configurable at run-time so I can optimize
the
performance of the server.

But... something also seems unreasonable:

1- In this framework only one thread can serve a socket at a given time
if I
issue only post zero-byte receive per socket. Is it a good idea to post
more
than one zero-byte receive per socket to handle IO while working with
more
than one IOCP threads?I do not know, you?

Yes, since only one zero-byte recv is posted at any given time only 1
thread
will work on a given socket. Posting multiple WSARecv() has a big
Disadvantage of making the code very complex and also increases the
overhead
of synchronization & packet sequencing. In my server I'm expecting
50KB/sec
of data transfer rate, so I have set the internal socket buffer to 16KB
and
am using one zero-byte recv to read all the data looping around recv() 3
times to ensure I read everything but not starve the resources. This
provides
very good performance, keeps the code simple and completely gets rid of
extra
synchronization overhead.

2- If I use overlapped WSARecv () to read actual data how can I know when
should I post zero-byte receives?

Not sure what you are asking but You post zero-byte receives using
WSARecv()
function by setting WSABUFF's len parameter to 0.

3- Is it possible that I completely misunderstood the idea behind
zero-byte
receives? Yes it is possible.So I will explain my understanding about
this
stuff, let's see what is this monster which comes to my nightmares every
night :
Zero-byte receive prevents large number of memory being locked. Because
of
the buffer it use is zero length, no memory is locked by OS. Thus a
server
can accept more client connections and can handle more IO before it reach
its locked memory limit.My responsibilty,as a developer, is to post zero
byte receives for all accepted clients as long as no data present for
that
client. When data received for a particuler client I should read all data
and then post another zero-byte receive. In summary if no data then no
non-zero byte WSARecv (). But how can I say "Yes, I read all data,I can
post a zero-byte receive and wait now"?


See my answer above, If you don't supply any buffer to WSARecv()'s WSABUFF
member (i.e. WSABUFF wb; wb.buff = NULL; wb.len = 0). This is called a
zero-byte recv. Since you are not supplying any buffer windows won't lock
up
any memory, this is really useful in case where a socket will connect and
sit
idle for a long time. However, if the socket connects, makes a request
and
disconnects then providing a buffer to WSABUFF may slighly help increase
the
performance.


.



Relevant Pages

  • About zero-byte receive (IOCP server)
    ... My new issue is about zero-byte receives. ... "...once the zero-byte receive operation completes, the server ... can simply perform a non-blocking receive to retrieve all the data buffered ... As far as understand the excerpt, I should make the socket non-blocking ...
    (microsoft.public.win32.programmer.networks)
  • Re: About zero-byte receive (IOCP server)
    ... sockets.The problem is that on completion of a zero-byte receive IOCP worker ... the socket to non-blocking mode and then issue non-overlapped,non-blocking ... On a zero-byte recv you don't have to read all the data, ... here, lets say the client has a high-speed connection, in this case the ...
    (microsoft.public.win32.programmer.networks)
  • Re: About zero-byte receive (IOCP server)
    ... sockets.The problem is that on completion of a zero-byte receive IOCP worker ... 1- In this framework only one thread can serve a socket at a given time if I ... can accept more client connections and can handle more IO before it reach ...
    (microsoft.public.win32.programmer.networks)