I have written a server and a client that are using an overlapped named pipe. My problem is mainly with Readfile() and GetOverlappedResult().

Note that this program is a test code. It will be integrated later in a framework (I'm porting linux code that uses AF_UNIX adress family for socket connections to Windows)

I describe the server part. I have 2 threads :

1) the main thread opens an overlapped named pipe, then loop over WaitForMultipleObjects(). WaitForMultipleObjects() waits for 3 events: the 1st one waits for a client to connect. The 2nd allows me to cleanly quit the program. The 3rd is signaled when an operation is pending in ReadFile().

2) The second thread is launched when the client is connected. It loops over ReadFile().

Here is the server code:


I mainly used MSDN doc (named pipe server using overlapped I/O, named pipe client), the SDK, and other doc on internet, to write that code. Look in [1] for the client code. The client code needs some love, but for now, I focus on making the server working perfectly.

There are 4 functions in the server code (i forget the function that display error messages):

a) svr_new: it creates the overlapped named pipe and the 3 events, and calls ConnectNamedPipe()

b) svr_del frees all the resources

c) _read_data_cb: the thread that calls ReadFile()

d) the main() function (the main thread), which loops over WaitForMultipleObjects()

My aim is to detect in _read_data_cb() when the client disconnects (ReadFile() fails and GetLastError() returns ERROR_BROKEN_PIPE), and when data comes from the client.

What I don't understand:

* Should I call GetOverlappedResult() ?
* If yes, where ? When ReadFile() fails and GetLastError() returns ERROR_IO_PENDING (line 50 of the paste) ? When WaitForMultipleObjects() returns (line 303 of the paste, I commented the code there) ? Somewhere else ?
* I do a ResetEvent of the event of ReadFile() when WaitForMultipleObjects() returns (line 302 of the paste). Is it the correct place to call it ?

With the code I pasted, here is the result if the client sends these 24 bytes (the ReadFile() buffer is of size 5 bytes. I intentionnaly set that value to test what to do if a client sends some data larger than the ReadFile() buffer)

message : "salut, c'est le client !"


$ ./server.exe waiting for client...
WaitForMultipleObjects : 0
client connected (1)
WaitForMultipleObjects : 2
* ReadFile : 5
WaitForMultipleObjects : 2
* ReadFile : 5
WaitForMultipleObjects : 2
* ReadFile : 5
WaitForMultipleObjects : 2
* ReadFile : 5
WaitForMultipleObjects : 2
* ReadFile : 4

Note: WaitForMultipleObjects() can be called less than that, it seems random. The number after "WaitForMultipleObjects :" is its returned value (2 == ReadFile() event) and the number after "ReadFile :" is the number of bytes read in the pipe when ReadFile() succeeds.

So, in my code, I do not call getOverlappedResult(), ReadFile() succeeds (il reads 5*4 + 4 = 24 bytes), but I don't know when the read operation has finished (WaitForMultipleObjects() returns several times, but i thought that it would have returned only when the read is complete).

Note: If I add a printf() when ReadFile() fails with ERROR_IO_PENDING, that printf() is called indefinitely.

In addition, the client sends 2 messages. The one above, and another one 3 seconds later. The 2nd message is never read and ReadFile() fails with the error ERROR_SUCCESS... (so to be precise, ReadFile() returns FALSE and GetLastError() returns ERROR_SUCCESS)

So, I'm completely lost. I have searched hours on Internet, in MSDN, in the SDK code (Server32.c and Client32.c). I still do not know what to do in my specific case.

So, ca someone explain me how to use GetOverlappedResult() (if I have to use it) to know how to check if the read operation finished, and where ? And even, if someone can fix my code :-) I gave the code so that everyone can test it (i find a lot of doc on internet, but it is almost always not precise at all :-/ )

thank you

[1] http://pastebin.com/fbCH2By8