John
John

Reputation: 1119

How to use Overlapped I/O with sockets?

I want to use Overlapped I/O in my server, but I am unable to find many tutorials on the subject (most of the tutorials are about Overlapped I/O with Completion Ports, and I want to use a callback function).

My server will have a maximum of 400 clients connected at one time, and it only send and receive data at a long periods of time (each 30 seconds a few kilobytes worth of data is exchanged between the server and the clients).

The main reason why I want to use Overlapped I/O is because select() can only handle a maximum of 64 sockets (and I have 400!).

So I will tell you how I understand Overlapped I/O and correct me if I'm wrong:

Upvotes: 0

Views: 3472

Answers (2)

Martin James
Martin James

Reputation: 24857

The IO completion callback mechanism works fine, I've used it a few times, no problem. In 32-bit systems, you can put the 'this' for the socket-context instance into the hEvent field of the OVERLAPPED struct and retreive it in the callback. Not sure how to do it in 64-bit systems:(

Upvotes: 0

Ben Voigt
Ben Voigt

Reputation: 283664

The one misunderstanding you appear to have is that OVERLAPPED callbacks are actually synchronous.

You said:

When the data is received and filled in the buffer, the callback function will be called

Reality:

When a call is made to an alertable wait function (e.g. SleepEx or MsgWaitForMultipleObjectsEx), if data has been received and filled in the buffer, the callback function will be called

As long as you are aware of that, you should be in good shape. I agree with you that overlapped I/O with callbacks is a great approach in your scenario. Because callbacks occur on the thread performing the I/O, you don't have to worry about synchronizing access from multiple threads, the way you would need to with completion ports and work items on the thread pool.

Oh, also make sure to check for WSA_IO_PENDING, because it's possible for operations to complete synchronously, if there's enough data already buffered (for receive) or enough space in the buffer (for send). In this case the callback will occur, but it is queued for the next alertable wait, it never runs immediately. Certain errors will be reported synchronously also. Others will come to your callback.

Also, it's guaranteed that your callback gets queued exactly once for every operation that returned 0 or WSA_IO_PENDING, whether that operation completes successfully, is cancelled, or with some other error. You can't reuse the buffer until that callback has happened.

Upvotes: 4

Related Questions