I need to transfer data between processes, I have a local server process and multiple clients process, they may send data and receive data at the same time.I create the namedpipe and CreateIoCompletionPort in server. And when the client CreateFile , the GetQueuedCompletionStatus will return which is what I expect, however, when the client writefile, the server cannot get Completion port package, I want the server to be notified when client come , out and send message, how should I do?
I know a little about the PostQueuedCompletionStatus function which can notify the completion port but I cannot get the Completion port handle in client process, could anyone tell me the common implementation, thanks!
Related
What I want to do is create a named pipe server that routes messages between connected peers. On Windows it seems that you first have to create a pipe and then connect it to a client and then you read from the connected client pipe to get the message you want and then that handle is bound to that client and you have to create a new named pipe. Is there no way to easily multiplex all the clients into one handle so I don't have to read from each client separately? To write to the clients from the server you obviously have to use the clients’ handle. Maybe the server can close the connection every time it has processed a request but that seems a bit unnecessarily wasteful. I would rather avoid implementing my own named pipes with shared memory...
"you first have to create a pipe and then connect it to a client"
Not exactly. The server process creates the pipe, but the client connects itself. Also, the client can try to connect and block if the server hasn't yet created the pipe.
"you read from the connected client pipe to get the message you want and then that handle is bound to that client". True. Doesn't stop you from immediately waiting for the next client.
"Is there no way to easily multiplex all the clients into one handle?". No, that would defeat the point of the HANDLE. That's the bit you need to demultiplex the clients.
What you seem to miss is that you can set the number of pipe instances to PIPE_UNLIMITED_INSTANCES, and read all of them using a shared LPOVERLAPPED_COMPLETION_ROUTINE callback. The callback will tell you which HANDLE and thus which pipe has data available.
I was wondering if there is any way to notify a server if a client side application was closed. Normally, if I Ctrl+C my client side terminal an EOF-signal is sent to the server side. The server side async_read function has a handle which has boost::system::error_code ec argument fed into it. The handle is called when the server side receives EOF-signal which I can happily process and tell the server to start listening again.
However, if I try to cleanly close my client application using socket.shutdown() and socket.close() nothing happens and the server side socket remains open.
I was wondering, is there a way to somehow send an error signal to the server-side socket so I could then process it using the error code?
The approaches described in comments covers 99% of cases. It doesn't work when client machine was (not gracefully) turned off, or network problems.
To get reliable notification of disconnected client you need to implement "ping" feature: to send ping packets regularly and to check that you received pong packets.
I need to create a server that allow ONE at time client connected.
The rule is that just one client can be connected and if the other one try to connect, can read a messagge like this "another client is connected, do you want disconnect it?".
Then if type yes the client will be disconnected.
My problem is about this step. How can I disconnect a client and connect the other one?
Can someone help me?
Thank you.
First build the abstract server structure. So you write a program which accepts TCP connections in one thread and pass them to a worker thread, which can read and send messages.
You should keep one Singleton containing a reference (or pointer, your choice) to the Worker with the currently connected client (or null, if there is noone connected).
To keep it simple, the acceptor thread should create a new Worker thread everytime it accepts a connection, and the Worker thread is terminated, when the connection breaks up.
Now you have to think about a protocol. For this simple task, 5 messages should be enough. Maybe every message ends with an endl, so you can use methods like readline if there is somthing like this in C++.
First, the CONNECT message. The server should return OK (second message), if noone is connected to it, and ERROR (third message), if there is already one connected.
The fourth message is CONNECTWITHDISCONNECT, it connects the client to the server and disconnects any other client. The newly connected client should receive a OK message from the server, and the disconnected one should receive DISCONNECT (fifth message).
Now, you could use the disconnect message also with the client, so one can disconnect, without requiring another to connect.
The client should send a CONNECT first, if it receives ERROR then, it can ask the user to disconnect the other client, and if the user wants to, the client sends CONNECTWITHDISCONNECT.
Another option (if you don't want to deal with multiple threads or multiple processes) is to use select() or poll() to handle multiple sockets at the same time within a single thread. In particular, you can select()-for-read on your accepting socket, and select() will return with that socket marked as ready-for-read whenever another client is trying to connect. Once you have accept()'d the client, you can pass the client's connection socket (as was returned by accept()) to select()'s read-sockets-set so that you will also be notified whenever the client's socket has bytes ready for you to read. And so on.
I am faced with a design issue regarding thread synchronization in C++, Windows.
I am writing a server application that starts one listening thread, which should stay active the whole time while the server is up.
When the listening thread gets a connect request, it opens a CONTROL socket and starts a new control thread.
This thread is used to send control data between server and a client, initializing server and all the background software to specific client data and starting data processing.
If the initialization (via control socket) is successful, the control thread will open a new socket, DATA socket, which is then used to pass data from server to client. It will also start two new threads, one which is sending on this new, DATA socket, and the other, which is receiving on the CONTROL socket, waiting if the client wants to terminate connection.
When client terminates connection ungracefully, by terminating application without the call to function which sends the server message to close the connection, here is what should happen:
Any of the threads in execution can detect this event. They will get some sort of error (WSAECONNRESET) while sending or receiving on DATA/CONTROL socket and should then signal all the other threads that they should stop executing (except for the server listening thread).
Which is the most natural way to achieve this type of behavior?
(I am using winsock (winsock2.h) for networking, and standard windows api (windows.h) for threading)
If you're writing a multi-threaded winsock server, you should be looking into IO completion ports. Using an IO completion port is the most scalable way to write a network service on the windows platform.
IO completion port based winsock servers use asynchronous communication, so instead of blocking on a socket, your threadpool receives completion packets when something interesting happens.
In any case, you'll be using WSARecv. When WSARecv returns non zero, call WSAGetLastError(). If you don't have WSA_IO_PENDING, then switch on the error and look for the winsock error code you're interested in.
The winsock error code WSA_OPERATION_ABORTED indicates that a socket has closed, although there are others (e.g. WSAECONNABORTED).
Would suggest a good text on the subject (e.g. Windows via C/C++).
You can use WSAEventSelect() function to associate event object with socket and create one event object for your events, then use these event objects in WaitForMultipleObjects() function, so your thread can wait for socket events and your custom events.
I was studying the MSDN examples of using named pipes:
Named pipe server using overlapped I/O
Named pipe client
The server easily detects when the client is disconnected and creates a instance of a named pipe. But I cannot figure out how the server knows that a client is connected to a pipe before any data from client is sent.
Can server detect a connceted client before client sends any data?
If server calls DisconnectNamedPipe before client disconnects itself first, will this disconnect the client as well? Can server disconnect a client from a pipe without negotiating it with the client?
Not sure I understand the hang-up. The server calls ConnectNamedPipe to wait for a client connection. No data needs to be sent. Nor can it be sent, you cannot issue a ReadFile until a client is connected. Note that the SDK sample uses this as well.
If the server disconnects ungracefully (without notifying the client with some kind of message so it can close its end of the pipe) then the client will get an error, ERROR_PIPE_NOTCONNECTED (I think). There's little reason to rely on that for a normal shutdown, you need to do something reasonable when the pipe server process crashed and burned unexpectedly.
Beware that pipes are tricky to get right due to their asynchronous nature. Getting errors that are not actually problems is common and you'll need to deal with it. My pipe code deals with these errors:
ConnectNamedPipe: ERROR_PIPE_CONNECTED on connection race, ignore
FlushFileBuffers: race on pipe closure, ignore all errors
WaitNamedPipe: ERROR_FILE_NOT_FOUND if the timeout expired, translate to WAIT_TIMEOUT
CreateFile: ERROR_PIPE_BUSY if another client managed to grab the pipe first, repeat
Server works incorrectly when clients get ERROR_FILE_NOT_FOUND error during WaitNamedPipe() or/and CreateFile() calls. This error code means there no pipes with specified name available on server. You should create new pipe on server immediately after ConnectNamedPipe() call to avoid this issue.