Boost ASIO async_connect succeeds when it should fail, why? - c++

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().

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 notify server of disconnect

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.

Trouble disconnecting and reconnecting socket (C++, winsock2)

I want the client program (TCP) to be ready to connect to the server program whenever the server starts to accept() incoming connections (the client program should always stay running, and the server program can start or end whenever it wants). The client code looks like this:
while (1) {
//Wait for the server to accept the connection:
while (connect(socket,(sockaddr*)&addr,sizeof(addr))!=0) {cout<<WSAGetLastError()<<endl;}
//Send whatever data...
}
On the first execution of the while (1) loop, everything runs as expected; when the client is connected to the server, it sends all the data, and the the server program is ended. Then I want the client to wait again at the while (connect(...,...,...)!=0) loop until the server starts again and accept()s a connection, but it does not connect to the server and WSAGetLastError() returns 10056, indicating that the socket is already connected (why?). I heard that you cannot reconnect the client after calling closesocket() on the socket, so I tried to disconnect the client before reconnecting by adding shutdown(socket,SD_SEND) to the while (1) loop but that doesn't work either.
Is there anything I can do besides repetitively waiting for the client program to end and starting it again? Is there some way to disconnect the client from the server program such that the client can reconnect later?
There's something seriously wrong with your application logic. You don't need to reconnect a connected socket; you can't reconnect a connected socket; and you can't reconnect a socket that has been closed, unless you're exploring one of the remote corners of the Windows API.

Simultaneous connection issue with boost SSL connection

Below pseudo code explains the situation I am facing
Server side
while (<some condition>)
{
// wait for SSL connection
acceptor.async_accept();
// wait until connection
io_service.run();
// perform handshake
ssl_socket.handhake();
// handshake successfully complete, start command manager thread
pthread_create();
io_service.reset();
// Go for the new connection waiting
}
What the problem here is I am able to connect two clients but not simultaneously.
1 connection arrives after which it takes 40-50 milliseconds for handshake and certificate verification and due to this reason any connection request in between fails.
Update:
Is there any way to stop listening client hello while handshaking is in progress?
I have to create new io_service instance for each loop as I might want to cancel the specific thread using io_service.stop() call. Does boost have any other option for the same?
The synchronous ssl_socket.handshake() will prevent additional connections from being accepted. Use ssl_socket.async_handshake() if you desire asynchronous behavior.
Also worth noting: you won't need a connection per-thread as that design won't scale beyond trivial examples.

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

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.