How to close boost asio server socket with all client sockets connected - c++

I use boost:asio::ip::tcp::acceptor to create server socket in my app. I close this acceptor socket using close function, than stop function in io_service but all connected client sockets closes only when my app is closed. How can i fix that?
Thanks!

Do either of the following:
invoke socket::close() on the sockets.
destroy the socket. See this answer for details on how the socket will be closed during destruction.
io_service::stop() only stops processing of the event loop. Work can still be posted into the io_service, and existing work will remain in the io_service. Thus, the application must call socket::close() on each of the sockets it wishes to close. For a portable graceful closure, call socket::shutdown() before calling close().
It may be worth taking the time to review Boost.Asio's HTTP Server 1 example. It uses a connection_manager to shutdown all connections.

Related

Do a server block execution when listening for client connection?

I'm new to socket programming and I want to create a client/server type of application using winapi. I want my application to be listening for a request from a client, and after serving the client it should continue listening for further requests. But before making an attempt I what to get an overview for understanding of the whole process. My question is when you call listen() on the server side, does the listen() block executes until a client tries to make a connection?
and after accepting and serving the current client, how does it get back to listening mode for other connections? because from the code I saw on the sites I visited there is no loop which calls listen() again after serving a client, it goes straight to close().
Please forgive me for not adding any code because I want to get basic knowledge before I can attempt it my self.
From the diagram as you can see doesn't block on listen()
Also, this link might help you.
From the block you can which are blocking calls
when you call listen() on the server side, does the listen() block executes until a client tries to make a connection?
No. listen() simply opens the listening port and establishes the backlog to hold pending connections, and then it exits. It is accept() instead that blocks waiting for a connection (if you use it in blocking mode, that is, which is the default).
after accepting and serving the current client, how does it get back to listening mode for other connections?
It is up to you to decide when that happens. The server will not go back to listening for a connection until you call accept() again. So you need to call accept() in a loop for the lifetime of your server. But, your server design will dictate WHEN you call accept().
If you want to service only 1 client at a time, then you simply have 1 loop that calls accept(), services the client in full, closes the accepted socket, and goes back to accept().
But, if you want to service multiple clients in parallel, then you need to accept clients as often as possible, either by calling accept() in a dedicated thread or select() loop, or by using AcceptEx() in the background by Overlapped I/O or an I/O Completion Port. Once a client has been accepted, you need to then decide whether you want to service the client directly in your select() loop, or in its own dedicated thread, or with Overlapped I/O or IOCP.
from the code I saw on the sites I visited there is no loop which calls listen() again after serving a client, it goes straight to close().
No, there is never a listen() loop. listen() is only to be called once, when opening the server port. But you do need an accept() loop instead to accept clients.
Please forgive me for not adding any code because I want to get basic knowledge before I can attempt it my self.
Literally, there are TONS of socket tutorals available online, and detailed WinSock documentation and examples on MSDN. All of them cover this topic.

Boost Asio TCP Server Handling multiple clients

I am new to network programming and the usage of Boost Asio library.
I successfully implemented a task for my requirement by modifying the Boost Asio "Blocking TCP Echo Server and Client" which performs transactions of operations between my Client and Server.
Now, I have a requirement where I need to connect multiple Clients with my Server.
I found some relevant links suggesting the usage of async_accept at the Server side.
So, I tried running the Boost Asio example: "Async TCP Echo Server" with the "Blocking TCP Echo client", where the server distinguishes the different clients and addresses them accordingly.
But, my actual requirement should be like, instead of the Server completing the entire process for one Client, it [the server] has to perform same operations for the first client then go to the second client and perform those operations and then again come back to the first client and continue in this order until all operations are complete.
Is there any way or idea which could help me perform this flow using Boost Asio? Also I'm just using the "Blocking TCP Echo Client", which just has a normal connect() and not an async_connect(), now is that a problem?
Also, is it possible to communicate between multiple clients through the server using Boost Asio?
Thanking you very much in advance!
There are 2 models to handling multiple client concurrently on the server.
The one is to spawn a new thread for each client and then each thread handles each client synchronously. The second model is to use asynchronous APIs on a single thread all operating on a single service. When the accept completes, you then create a new worker thread and start the worker off the send and recv required by your protocol. You main thread goes back the accepting new connections.
With async, you prime the pump with an async accept and the call io_service run. When the accept completes, your callback runs. You now prime the pump again with further accepts (for more client) start async send and recv for the newly created client. Since all sends and recvs are non-blocking, the only time your thread sleeps is when it has nothing to do. Otherwise the io_service run method takes care of everything for you.
If you are blocking on sends and recvs, through, you cannot process more than one client concurrently.

Interrupting accept()

Is there a OS portable way of interrupting a blocking accept? I have a multi-threaded deamon/service that needs to gracefully close all listening network hosts when the deamon/service gets a shutdown signal. I see that some say you should use non-blocking sockets or select with a time-out - but won't these degrade performance as my application should be as fast as possible? The deamon runs in the main thread while each of the listening network hosts run in their own thread. The problem now is that accept wait indefinitely if there is no network traffic on the listening network host's socket. If I should use signals, then is there an example somewhere of using signals to interrupt accept?
The solution here is to not call accept when there's nothing to do. Just use non-blocking select or poll to wait until there's something to accept, then accept at that point. Unless you create a really tiny timeout there won't be any performance implications of waking up from the non-blocking call and going back to wait on that socket again.

Boost ASIO async_connect succeeds when it should fail, why?

I have a server application in which I accept only one client with boost::asio::ip::tcp::acceptor and async_accept.
I run the client application and successfully connect using a boost::asio::ip::tcp::socket and the async_connect member function.
Then I make the client crash (CTRL-ALT-DEL).
If I restart the client application, and try to reconnect, it succeeds...
Even though I do not redo an async_accept on the server side.
How is this possible?
EDIT:
If the server application is not running, the async_connect fails as it should.
It is possible because the acceptor is still in a listening state. While in a listening state, incoming connections will be queued until they are accepted by an accept() operation. More details on an acceptor's states and operations can be found in this answer.
To get the desired behavior, simply close() the acceptor after a connection has been accepted. After the connection closes, transition the acceptor back into a listening state, by performing open() -> bind() -> listen().

Signaling all active threads (Windows)

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.