C++ Can I make boost::asio connection socket without timer? - c++

I have a window server socket and a Linux client socket. Client connect to server and send a message. After, the server will call a external executable. The problem is : when server is not available, Client is blocking with timeout at connect function, But I don't want it. I hope if the connection is not made, client socket will be closed straight away.
Somebody can give me some advice?

Warning: Pseudo-Code ahead.
You can do that. But it is not as straight forward as you might hope.
You need to use async_connect() from your client to not block. Then you also need a deadline_timer set to whatever timeout you deem appropriate. Zero will not work, you need to give the async_connect() some time. But i guess one or two seconds should be fine.
The timers handler will then have to cancel() all async operations on the socket (you need to make sure that is only the connect, use more sockets if needed).
Mind the socket will not be closed by that. Ideally you will close it in the handler of the async_connect whenever the passed error_code indicates a negative result. For example, if it was canceled, the handler will be called with OPERATION_ABORTED as error_code.
Of course, if you check only for that, you could as well close() the socket in the timers handler after the cancel(). But that would leave you with an open socket whenever the async_connect failed for some other reason.
I would assume from your question that you want your socket to get closed whenever the async_connect() passes any error_code but SUCCESS. And SUCCESS is the only error_code implicitly converted to 0 when used as a boolean, so checking for that in your handler is easy. ^^
Do not forget to cancel the deadline_timer in the handler of the async_connect() and to make sure the timers handler was not called with OPERATION_ABORTED before it closes the socket. ^^

Related

How to tell if a client is attempting to connect to server in c++ winsock

I want a server to accept a client with this code
SOCKADDR_IN cliaddr = { 0 };
int len = sizeof(cliaddr);
_sockClient = accept(_sockServer, (SOCKADDR*)&cliaddr, &len);
Both _sockClient and _sockServer are SOCKETs, _sockServer's SOCKET already connected to the server.
Before I accept, I want to check _sockServer if there is an incoming client request to join. I'm pretty sure there is a way to do this, though I don't know how. Does anyone know?
By default, a socket operates in blocking mode. So, you could simply call accept() and let it block the calling thread until a new connection is accepted. That is the easiest approach. If you don't want to block the calling thread, you could call accept() in another thread instead.
But, provided you don't want to block any thread at all, then yes, there are other ways to handle this, depending on your programming model:
Poll the socket using the readfds parameter of select(). The socket will be in a readable state if it has any pending connections waiting to be accepted.
Use WSAEventSelect() to signal a waitable WSAEVENT object whenever an FD_ACCEPT event occurs, indicating that pending connections are available to accept. You can then poll/wait on that object using WSAWaitForMultipleEvents(), and use WSAEnumNetworkEvents() to reset the object's state for the next wait.
Use WSAAsyncSelect() to receive a window message whenever an FD_ACCEPT event occurs.
Use AcceptEx() instead of accept() to start an asynchronous acceptance in the background. It will report its completion to you via Overlapped I/O or an I/O Completion Port.
See Overlapped I/O and Event Objects in Winsock's documentation for more details.

Why should I use shutdown() before closing a socket? [duplicate]

This question already has answers here:
close vs shutdown socket?
(9 answers)
Closed 6 years ago.
On this MSDN page:
Sending and Receiving Data on the Client
It recommends closing the sending side of the socket by using:
shutdown(SOCK_ID, SD_SEND);
Why should I?
Maybe I dont have to, and its just a recommendation? Maybe its for saving memory? Maybe for speed?
Does anyone have an idea?
The answer is in the shutdown() documentation:
If the how parameter is SD_SEND, subsequent calls to the send function are disallowed. For TCP sockets, a FIN will be sent after all data is sent and acknowledged by the receiver.
...
To assure that all data is sent and received on a connected socket before it is closed, an application should use shutdown to close connection before calling closesocket. One method to wait for notification that the remote end has sent all its data and initiated a graceful disconnect uses the WSAEventSelect function as follows :
Call WSAEventSelect to register for FD_CLOSE notification.
Call shutdown with how=SD_SEND.
When FD_CLOSE received, call the recv or WSARecv until the function completes with success and indicates that zero bytes were received. If SOCKET_ERROR is returned, then the graceful disconnect is not possible.
Call closesocket.
Another method to wait for notification that the remote end has sent all its data and initiated a graceful disconnect uses overlapped receive calls follows :
Call shutdown with how=SD_SEND.
Call recv or WSARecv until the function completes with success and indicates zero bytes were received. If SOCKET_ERROR is returned, then the graceful disconnect is not possible.
Call closesocket.
...
For more information, see the section on Graceful Shutdown, Linger Options, and Socket Closure.
In other words, at least for TCP, calling shutdown(SD_SEND) notifies the peer that you are done sending any more data, and that you will likely be closing your end of the connection soon. Preferably, the peer will also do the same courtesy for you. This way, both peers can know the connection was closed intentionally on both ends. This is known as a graceful disconnect, and not an abortive or abnormal disconnect.
By default, if you do not call shutdown(SD_SEND), closesocket() will attempt to perform a graceful shutdown for you UNLESS the socket's linger option is disabled. It is best not to rely on this behavior, you should always call shutdown() yourself before calling closesocket(), unless you have good reason not to.
It is unnecessary and redundant except in the following cases:
You want to achieve a synchronized close as described in the documentation quoted by Remy Lebeau.
The socket has been duplicated somehow, e.g. it is shared with child or parent processes or via the API, and you want to ensure the FIN is sent now.
Your application protocol requires that the peer receive a shutdown but needs to continue to send. This can arise for example when writing a proxy server.
You may have unread data in your socket receive buffer and you want to close and ignore it and send a FIN before provoking a connection reset, which will happen when you close if there is unread pending data.
These are the only cases I've ever come across in about 30 years: there may be others but I'm not aware of them.
There are no specific resources associated with sending or receiving operation on the socket, the socket is either used or closed. There reason for shutdown is not related to resource-management. Shutting down the socket is implementation of so-called graceful shutdown protocol, which allow both sides of the communication to realize the connection is going down and allows to minimize loss of data.

how to cancel a `boost::asio::read` operation while it's waiting

I am using boost::asio to transfer data to & fro from client to server. I have a reader thread on client side to read data received on the socket on client side. Please note that I am using boost::asio::read on client side & boost::asio::writeon server side.
Not using async_read or async_write. Everything works great.
However when I close my application, 2 out 10 times the app does not cleanly tear down or close properly. It gets hung while closing down The issue is the following:
My closing function gets called when destructors get called during my app's close down. Following is the code of the Close function:
socket.cancel();
socket.close();
boost::system::error_code ec;
socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
The problem is that the boost::asio::read call does not return when it does not get any data & keeps waiting on it. This should be fine as long as I can cancel it. I am trying to do a socket.cancel on it to cancel all read operations while exiting.
However, it doesn't seems to work. I read in some forums that socket.cancel only cancels async_read operations. Is it so ? Then what is the way to cancel a boost::asio::read` operation when my app needs to exit ?
That's the nature of blocking IO.
Indeed socket.cancel() (or even io_service::stop()) will not work on synchronous operations.
The only way to interrupt this is to use socket-level timeouts (but Asio doesn't expose that) or to use asynchronous signals (e.g. pressing Ctrl-C in a terminal sends the child process a SIGINT).
I've previously created a poor-man's wrapper if you insist on running single operations with a timeout:
boost::asio + std::future - Access violation after closing socket
boost::system::error_code _error_code;
client_socket_->shutdown(boost::asio::ip::tcp::socket::shutdown_both, _error_code);
Above code help me close sync read immediately.
And sync read wiil return with error code: boost::asio::error::eof
I wonder why your code socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec); did not work.
Maybe you should try again.
The error is due to the call to socket.close() before the call to socket.shutdown(). If you close a socket while there is a pending synchronous read(), you will occasionally get that error. It is really due to an expected data race in the underlying asio socket code.
Try removing the socket.close() call. Assuming your socket is wrapped in some kind of shared_ptr, you can let the socket destructor close the underlying socket.
You will still want to call socket.cancel() and socket.shutdown() explicitly in your use case in order to cancel outstanding operations.

Why does my Winsock app sometimes wait at listen() and sometimes at accept()?

Hey guys I'm using Visual C++ 2010, trying to write a server/client app using Winsock... I'm not sure why, but sometimes the server waits at the listen() function, and sometimes at the accept(). Just wondering, what is the mechanism of these two functions? Isn't it supposed to wait at listen() until it hears an incoming connection and then proceed to accept()?
The listen function puts the socket into listening mode. You have to call this functions only once. Normally, this function returns immediately.
The incoming connections are accepted by calling accept function. In the blocking mode (default) it returns only when a new connection is accepted or an error occurs.
It doesn't. Your observations are faulty. listen() is not a blocking call. All it does is put the port into LISTENING state, and that either succeeds or it fails. There's nothing to block for.
It is accept() which blocks, waiting for an inbound connection.

boost::asio sync server is not accepting connections after first one

I am writing simple synchronous asio server.
Workflow is following - in endless cycle accept connections and create thread for each connection. I know, this is not so optimal, but async is too hard for me.
Here's my ugly code:
std::vector<asio::io_service*> ioVec;
std::vector<std::thread*> thVec;
std::vector<CWorker> workerVec;
std::vector<tcp::acceptor*> accVec;
while (true) {
ioVec.emplace_back(new asio::io_service());
accVec.emplace_back(new tcp::acceptor(*ioVec.back(), tcp::endpoint(tcp::v4(), 3228)));
tcp::socket* socket = new tcp::socket(*ioVec.back());
accVec.back()->accept(*socket);
workerVec.push_back(CWorker());
thVec.emplace_back(new std::thread(&CWorker::run, &workerVec.back(), socket));
}
The problem is first connection being done, it's correctly accepted, thread is created, and everything is good. Breakpoint is correctly triggered on "accept()" string. But if I want to create second connection (it does not matter if first is DCed or not) -> telnet is connected, but breakpoint on next string to "accept" is not triggered, and connection is not responding to anything.
All this vector stuff - I've tried to debug somehow to create separate acceptor, io_service for any connection - not helped. Could anyone point me where is error?
P.S. Visual Studio 2013
The general pattern for an asio-based listener is:
// This only happens once!
create an asio_service
create a socket into which a new connection will be accepted
call asio_service->async_accept passing
the accept socket and
a handler (function object) [ see below]
start new threads (if desired. you can use the main thread if it
has nothing else to do)
Each thread should:
call asio_service->run [or any of the variations -- run_one, poll, etc]
Unless the main thread called asio_service->run() it ends up here
"immediately" It should do something to pass the time (like read
from the console or...) If it doesn't have anything to do, it probably
should have called run() to make itself available in the asio's thread pool.
In the handler function:
Do something with the socket that is now connected.
create a new socket for the next accept
call asio_service->async_accept passing
the new accept socket and
the same handler.
Notice in particular that each accept call only accepts one connection, and you should not have more than one accept at a time listening on the same port, so you need to call async_accept again in the handler from the previous call.
Boost ASIO has some very good tutorial examples like this one