How is it possible to repeatedly read from a NamedPipe in Windows? I get an 109 error, saying it could not open pipe, if I have a ReadFile() function after another ReadFile() function.
of course this is possible and need do after your pipe is connected and until disconnect. 109 this is ERROR_BROKEN_PIPE - you got this error in ReadFile when another end is close pipe handle, by call CloseHandle. in this case you need call DisconnectNamedPipe and then wait for new client by call ConnectNamedPipe. after connection is complete - you need just call ReadFile , in read completion again call ReadFile and so on until disconnect - some error returned. if you got error ERROR_PIPE_NOT_CONNECTED in ReadFile (just or in completion) this mean that remote end call DisconnectNamedPipe - your pipe already disconnected, so you can skip call to DisconnectNamedPipe and just call ConnectNamedPipe.
Related
I have two Win32 console processes a) a server process and b) a client process.
The Server Process:
i) It creates a IO completion port by calling CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 1).
ii) Spawn a worker thread and waiting to run the worker thread. The worker thread blocks on GetQueuedCompletionStatus() inside a loop. It simply logs the values which are coming on GetQueuedCompletionStatus().
iii) Create a named pipe (inbound)
iv) Associate the pipe with the IOCP
v) Connect the named pipe and waiting until the overlapped operation completed in the case of getting ERROR_IO_PENDING
vi) The server thread blocks (using GetMessage loop) until it detects any termination message which will be generated on pressing a key to terminate the server process.
vii) On getting a termination message it posts a completion packet to the IOCP to terminate the worker thread.
viii) After worker thread termination, it disconnects the named pipe, close the handles of the named pipe and IOCP.
The Client Process:
i) Open the named pipe by calling CreateFile().
ii) After successful connection, It writes a string to the pipe by calling WriteFile() and waiting for 10 seconds.
Problem: When the client opens the pipe by calling CreateFile() the server worker thread deque a completion packet (where bytes transferred=0) and GetQueuedCompletionStatus() is returning success code. But when the client is writing the buffer to the pipe, nothing is coming to the worker thread and it remains in blocked state though WriteFile() is returning success. I think that I am missing something. Please help.
(this is an updated repost of a previously asked question, posted with old account which I've lost the credentials for)
I'm writing a client-server program, where the client is C++/winapi and the server is C#/.net.
socket is an AF_INET/ SOCK_STREAM and I'm using Readfile() and WriteFile() for socket IO at client.
the client have a loop where it reads from server (and may block the calling thread [denote t1] , which is fine with me). it also have another thread [denote t2] , that wait on an Event object with a timeout.
if the timeout is reached (and the Event is yet to be singled) the t2 thread, will write (exacly on byte) on the same socket.
The problem I have, is that it seems like the write won't return untill the read on t1 returns (in some legitimate scnerions it will never happen) , as if the socket was not full-duplex.
I've checked it buttom to top, there are no other thread-related comlications. I acctually ran the client from a diffrent machine, and used wireshark to sniff traffic. After the timeout was reached, there was nothing on the wire (no matter how long I wait) , untill I wrote some data from server side (so the read() on t1 returned) - and just right after that, the write() of client is finally transmitted.
As I explained in your earlier question, sockets are full duplex. A read in one thread will not block a write in another thread, and vice versa.
How can I find out whether TCP connection was torn down by the peer (by sending RST packet or similar) using Windows IOCP API? Specifically, I can't send or receive any data -- there's no overlapped operation going on. I just want to get an asynchronous notification. Is there a way to do that?
You need to have a read or write pending to detect connection closure. Either will return as Remy suggests on RST but with a pending read you'll also get notification of when the remote side closes the send side of its connection.
I suggest you always keep an overlapped read pending, if you don't want to tie up memory you can always make this a zero byte read.
Your IOCP completion handler will be notified whether a socket operation succeeds or fails. The parameters tell you which is the case.
If you are using GetQueuedCompletionStatus(), it will return FALSE if any failure occured. If it was a socket failure, *lpOverlapped will be set to the non-NULL pointer value of the OVERLAPPED operation that failed. If GetQueuedCompletionStatus() itself failed, *lpOverlapped will be set to NULL. If the peer disconnects gracefully, it will return TRUE and set *lpNumberOfBytes to 0 instead.
If you are using WSAgetOverlappedResult(), it will return FALSE if any failure occurs. Use WSAGetLastError() to determine if it was a socket failure or not. If the peer disconnects gracefully, it will return TRUE and set *lpcbTrasfer to 0 instead.
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 to unix that uses AF_UNIX adress family for socket connections)
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:
http://pastebin.com/5rka7dK7
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 !"
output:
$ ./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.
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.
Note: I 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 3seconds 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
Take a look at I/O Completion Ports. In my opinion it's the most efficient way to receive and handle notifications about overlapped operations in Windows. So basically you will need to use GetQueuedCompletionStatus and GetQueuedCompletionStatusEx in blocking and non-blocking mode when you're ready to process new completion events, instead of calling GetOverlappedResult from time to time. As a matter of fact, you can even get rid of WaitForMultipleObjects completely.
Also, which flavor of Unix are you targeting? In Solaris there's a very similar abstraction. Check out man port_create.
Unfortunately, there's nothing similar in Linux. Signals (including real-time) can be used to some extent as waitable completion objects, but they are not as comprehensive as the ports in Windows and Solaris.
Friends,
I have a non-blocking TCP socket (on AIX). When I attempted connect() I got EINPROGRESS. My question is if I call recv() before connection completion, what would be the (most apprpriate) error code?
I saw that, in case connection fails, and I call recv(), I got ECONNREFUSED; means I got an error corresponding to my earlier connect() attempt. Taking same logic I should get EINPROGRESS for recv(). Am I right in my approach ?
If yes, this raises another question - Why such error codes are not included amongst error codes of recv()?
I have only seen EAGAIN returned in this case, just as you would see in the case where there's no data to read. For writing to a non-connected socket, you typically get ENOTCONN, though I believe some platforms might give you EAGAIN.
Here's a trivial Python script to demonstrate:
import socket
# Any address that does not succeed or fail right away will do
ADDR = "192.168.100.100"
PORT = 23
s = socket.socket()
s.setblocking(False)
try:
s.connect((ADDR, PORT))
except socket.error, e:
print "Connect gave us",e
try:
s.recv(1)
except socket.error, e:
print "Read gave us",e
try:
s.send("x")
except socket.error, e:
print "Write gave us",e
For me, it gives:
Connect gave us (36, 'Operation now in progress')
Read gave us (35, 'Resource temporarily unavailable')
Write gave us (57, 'Socket is not connected')
These are EINPROGRESS, EAGAIN, and ENOTCONN respectively.
You are operating on a non-blocking socket, which is perfect fine to return EINPROGRESS, which indict that the connection establishment has not being finished yet, this is documented in connect's page:
EINPROGRESS
The socket is nonblocking and the connection cannot be completed immediately. It is possible to select(2) or poll(2) for completion by
selecting the socket for writing. After select(2) indicates writability, use getsockopt(2) to read the SO_ERROR option at level SOL_SOCKET
to determine whether connect() completed successfully (SO_ERROR is zero) or unsuccessfully (SO_ERROR is one of the usual error codes listed
here, explaining the reason for the failure).
So you will need select/pool to make sure the socket is writable, and get error from SO_ERROR.