What is the easiest way to check if a socket was closed on the remote side of the connection? socket::is_open() returns true even if it is closed on the remote side (I'm using boost::asio::ip::tcp::socket).
I could try to read from the stream and see if it succeeds, but I'd have to change the logic of my program to make it work this way (I do not want data to be extracted from the stream at the point of the check).
Just check for boost::asio::error::eof error in your async_receive handler. It means the connection has been closed. That's the only proper way to do this.
Is there a boost peek function available? Most socket implementations have a way to read data without removing it from the queue, so you can read it again later. This would seem to satisfy your requirements.
After quickly glancing through the asio docs, I wasn't able to find exactly what I was expecting, but that doesn't mean its not there.
I'd suggest this for starters.
If the connection has been cleanly closed by the peer you should get an EOF while reading. Otherwise I generally ping in order to figure out if the connection is really alive.
I think that in general once you open a socket, you should start reading it inmediately and never stop doing so. This way you can make your server or client to support both synchronous and asynchronous protocols. The moment the client closes the connection, the moment the read will tell you this.
Using error_code is able to check the condition whether the client is connected or not. If the connection is success, the error_code error.value() will return 0, else return other value. You can also check the message() from the error_code.
boost::asio::socket_base::keep_alive keepAlive(true);
peerSocket->set_option(keepAlive);
Enable keep alive for the peer socket. Use the native socket to adjust the keepalive interval so that as soon as the connection is closed the async_receive handler will get EOF while reading.
Configuring TCP keep_alive with boost::asio
Related
What I know...
I need to call set_option(tcp::no_delay(true)) before connect() according to https://stackoverflow.com/a/25871250 or it will have no effect.
Furthermore, set_option() works only if the socket was opened beforehand according to https://stackoverflow.com/a/12845502.
However, the documentation for async_connect() states that the passed socket will be closed if it is open before handling the connection setup (see async_connect()).
Which means that the approach I chose does not set NO_DELAY correctly (I have tested this on Windows 7 x64 so I can say for sure).
if ( socket.is_open() ) {
socket.close();
}
socket.open(tcp::v4());
socket.set_option(tcp::no_delay(true));
socket.async_connect(endpoint, bind(&MySession::connectComplete, this, asio::placeholders::error));
Question: How can I set NO_DELAY with Boost ASIO correctly to open a client connection?
P.S.: I am using Boost 1.53. Switching to another Boost version is not easiliy possible for me.
P.P.S.: Not setting NO_DELAY in my program but for the network interface in the registry solves this issue but this will affect all applications which is not my intention. See description.
The async_connect() free function will close the socket:
If the socket is already open, it will be closed.
However, the socket.async_connect() member function will not close the socket:
The socket is automatically opened if it is not already open. If the connect fails, and the socket was automatically opened, the socket is not returned to the closed state.
The following code will set the no_delay option on an open socket, and then initiate an asynchronous connect operation for the open socket:
socket.open(tcp::v4());
socket.set_option(tcp::no_delay(true));
socket.async_connect(endpoint, handler);
Just set it right after connection. Nagle algorithm works after you send any data before kernel received ASK packet. So it does not matter for connect operation. Just set it right after connect, before any send.
socket.async_connect(ep, yield);
socket.set_option(tcp::no_delay(true));
I need to enforce the return value of read from a socket to equal to zero without closing connection.
I read the following statement in a page saying:
If an end-of-file condition is received or the connection is closed, 0 is returned.
But I don't know how to make it receive that condition after the string I have sent.
Can anyone help?
I'm afraid you can't do that.
If you want read to return zero, you need to close the socket. If you don't want to close the socket, you need to signal "end-of-communication" or "end-of-message" as part of your protocol.
A common way of doing that is prefixing each message with its length. That way the receiving side knows when it's read a complete message and do whatever it wants with it.
If you want the peer's read() or recv() to return zero, you must either close the socket or shut it down for output. In either case you can't sent anything else afterwards. If that constraint doesn't suit you, you will have to revise your requirement, as it doesn't make sense.
Both the "end of file condition" and the "connection closed" condition tell the receiver that no more data can be received on this socket. You cannot simulate that by sending some magic data.
Besides of calling close on the socket you can use shutdown(2) on the socket to only close either the reading side or the writing side. This might help in limited cases but not in the general case.
Perhaps you need some multiplexing syscall like poll(2).
You definitely need to read some good material like Advanced Linux Programming or Advanced Unix Programming.
If you need the TCP/IP transmission to transit application messages, you need to care about packaging and fragmenting explicitly yourself (either by having fixed-size messages, or by having some way to know the logical message size during transmission). Be aware that TCP/IP transmission can be fragmented by the network.
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Send buffer empty of Socket in Linux?
I want to create a socket server sending some data to a connecting client and disconnect him again.
I'm using non-blocking sockets so I don't know how to figure out if all data have at least been sent (send?) correctly (in short: no more data in my send buffer).
I don't want to keep the connection established if it's not neccessary anymore because I can't ensure that the client disconnects on his own.
Currently I'm just shutting down the client using shutdown() and later close(). But testing showed me a client does not always recieve all data before the connection gets closed.
There must be a way to ensure all data got send before closing the connection on non-blocking sockets, too, isn't there? Hope my question is clear enough and you can help me (:
The only way you can know your data has been sent prior to ending the connection is for the peer to acknowledge it in the application protocol. You can ensure that both ends get to EOS at the same time by shutting down for output at both ends and then reading to EOS at both ends, then closing the socket at both ends.
you can send the file size prior to data of the file. While closing the socket just check the file size and take appropriate action to close or resend the file....
I'm writing an IRC client in C++ and currently I'm having an issue where, upon exit, I do:
Send("QUIT :Quit\r\n"); // just an inline, variadic send() wrapper
shutdown(m_hSocket, SD_BOTH);
closesocket(m_hSocket);
WSAShutdown();
However, the issue is that the QUIT message is not being sent. I've sniffed the packets coming from the client and infact this message is never sent. I believe this is an issue with the socket not being flushed, but I have no idea how to do this and Google suggested disabling Nagle's algorithm but I doubt this is good practice.
Thanks in advance.
First of all you should check the return value of send: are the data you attempt to send actually accepted by the network stack? (In general this should be done after each and every send call, not just in this case).
Assuming the data is accepted, then AFAIK it should be actually transmitted as a result of calling shutdown. You might try using SO_LINGER to see if it makes a difference, see Graceful Shutdown, Linger Options, and Socket Closure on MSDN.
Initial questions here
So I've been reading up on asynchronous sockets, and I have a couple more questions. Mostly concrete.
1: I can use a blocking socket with select() without repercussions, correct?
2: When I use FD_SET() I'm appending the current fd_set* not changing it, correct?
3: When using FD_CLR(), I can simply pass in the socket ID of the socket I wish to remove, right?
4: When I remove a socket, using FD_CLR(), is there a prefferred way of resetting the Max File Descriptor (nfds)?
5: Say I have all of my connected sockets in a vector, when select() returns, I can just itterate through that vector and check if (FD_ISSET (theVector[loopNum], &readFileSet)) to see if any data needs to be read, correct? And if this returns true, I can simply use the same receiving function I was using on my synchronous sockets to retreive that data?
6: What happens if select() attempts to read from a closed socket? I know it returns -1, but does it set errno or is there some other way I can continue to use select()?
7: Why are you so awesome? =D
I appreciate your time, sorry for the headache, and I hope you can help!
Yes
Unclear? FD_SET inserts a socket into the set. If the socket is already there, nothing changes.
FD_CLR removes a socket from the set, if the socket isn't there nothing's changed
You could keep a parallel set<> of sockets, then get the highest value from there. Or you could just set a bool saying "rescan for nfd before next select" (NOTE: On windows nfd is ignored)
Correct
If select fails, the quick fix is to iterate sockets and select() on each of them one by one to find the bogus one. Optimally your code should not allow select() on a socket you have closed though, if the other end closed it it's perfectly valid to select on.
I need to get you to talk to my wife.
So I've been reading up on asynchronous sockets
Judging by what follows I don't think you have. You appear to have been reading about non-blocking sockets. Not the same thing.
1: I can use a blocking socket with select() without repercussions, correct?
No. Consider the case where a listening socket becomes readable, indicating an impending accept(), but meanwhile the client closes the connection. If you then call accept() you will block until the next incoming connection, preventing you from servicing other sockets.
2: When I use FD_SET() I'm appending the current fd_set* not changing it, correct?
No. You are setting a bit. If it's already set, nothing changes.
3: When using FD_CLR(), I can simply pass in the socket ID of the socket I wish to remove, right?
Correct.
4: When I remove a socket, using FD_CLR(), is there a preferred way of resetting the Max File Descriptor (nfds)?
Not really, just re-scan and re-compute. But you don't really need to reset it actually.
5: Say I have all of my connected sockets in a vector, when select() returns, I can just itterate through that vector and check if (FD_ISSET (theVector[loopNum], &readFileSet)) to see if any data needs to be read, correct?
Correct, but it's more usual just to iterate through the FD set itself.
And if this returns true, I can simply use the same receiving function I was using on my synchronous sockets to retreive that data?
On your blocking sockets, yes.
6: What happens if select() attempts to read from a closed socket?
select() doesn't 'attempt to read from a closed socket. It may attempt to select on a closed socket, in which case it will return -1 with errno == EBADF, as stated in the documentation.
I know it returns -1, but does it set errno or is there some other way I can continue to use select()?
See above.