Jump to content

View more

Image of the Day

Adding some finishing touches...
Follow us for more
#screenshotsaturday #indiedev... by #MakeGoodGames https://t.co/Otbwywbm3a
IOTD | Top Screenshots

The latest, straight to your Inbox.

Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.


Sign up now

c++ asio

4: Adsense

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.


  • You cannot reply to this topic
3 replies to this topic

#1 Anders Elton   Members   

190
Like
0Likes
Like

Posted 21 March 2012 - 08:02 AM

Hey, I have a problem detecting disconnect when the network cable is pulled.

Every 60 seconds i send out a "heartbeat" packet from server to all connected clients, which in our protocol is a payload and crc (8 bytes)

The client does nothing with this packet.

the server is using async_write
boost::asio::async_write(m_Socket, asyncData, boost::bind(&net::BoostConnection::HandleWrite, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, ptr_tmp_cast(this)));

void net::BoostConnection::HandleWrite(const boost::system::error_code& errorCode, size_t bytesWritten, Ptr_c<net::BoostConnection> self)

Even when the network cable is unplugged, i get successfull writes in the HandleWrite callback. errorCode is is not set to indicate peer errors, and the amount of bytes written is 8, as expected.

The server is initalized like this:
bool net::NetServerBase::Start(unsigned short port)
{
boost::system::error_code errorCode;
boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port);
m_Acceptor.open(endpoint.protocol());
m_Acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
m_Acceptor.set_option(boost::asio::ip::tcp::no_delay(true));
if ( m_Acceptor.bind( endpoint, errorCode) )
{


.....
}

The async accept initalizes socket with these socket options:

m_Socket.set_option(boost::asio::ip::tcp::no_delay(true));
m_Socket.set_option(boost::asio::socket_base::reuse_address(true));

Are there any more options i need to set so a timeout is detected earlier? I thought that if cable was pulled and I sent data, i would get an immidiate response that the data failed. obviously I am either doing something wrong, or have misunderstood something!

Any help would be appriciated!
www.ageofconan.com

#2 Antheus   Members   

2409
Like
2Likes
Like

Posted 21 March 2012 - 08:27 AM

I thought that if cable was pulled and I sent data, i would get an immidiate response that the data failed.


Writes to socket go into buffer. Network stack in kernel then retries for a certain amount of time, can be up to 30 seconds or so. It's how TCP is designed to work. So unless kernel reports actual cable disconnect, perhaps by disabling the network interface and invalidating all open connections (not the common case IIRC), clients won't know about connection loss, just like they don't know about problems further down the line.

Increase frequency of heartbeats. If such a heartbeat is missed, close the socket, concluding the client has disconnected. If heartbeats are sent once every 3 seconds, it will give a timeout latency of that much. Downside of this approach is that periodic lag spikes longer than that disconnect clients.

Alternatively, under request/response model, set a timeout for confirmation on per-request basis. When a message is sent, if response isn't received in X ms, assume client has lagged out. Such approach allows selective confirmation where some messages aren't acked or may have long timeouts, but is again susceptible to lag spikes.

Related exploit - a hidden boss was found in D3 beta by doing just that. Disconnect cable, run past portal, connect cable and bam, you're where you're not supposed to be. Also, rogues liked to do that in pvp.

Using a heartbeat of 10-15 seconds might be OK for action-oriented networking, more for non-interactive.

#3 Anders Elton   Members   

190
Like
0Likes
Like

Posted 21 March 2012 - 08:40 AM

Thank you for your reply,

Do you know how I can see the values for retries/etc in kernel?

The disconnect happens about 12 minutes (so about 12 heartbeats) after cable was pulled.

As I said the client is not responding to the heartbeats. It is just the server sending data, not expecting any response.

If this turns out to be a bad idea, i can just go a bit higher level and write some ping/pong code, and disconnect if reply is not given in decent timeframe.

I would however, prefer to get my initial plan working, if it is doable.
www.ageofconan.com

#4 Antheus   Members   

2409
Like
0Likes
Like

Posted 21 March 2012 - 08:50 AM

TCP doesn't have a "cable disconnected" state by very design. So there is nothing in sockets that could help, in this particular case you merely know that cable was disconnected. Problems with connection can occur anywhere, the undersea optic cable might have been cut.

TCP can only detect disconnect if it receives connection close/reset. Until then, it assumes connection is valid, even if round trip takes hours or days.

If this turns out to be a bad idea, i can just go a bit higher level and write some ping/pong code


This is what heartbeats already are. If they don't arrive, client isn't there anymore.


You don't really care what caused the disconnect and who pulled it. Even if you detect on your side, other end might have done the same. What you need to monitor is responsiveness.

Track the time it takes for client to respond to requests. If no response arrives for 10 seconds, assume client is dead. Or, if no messages arrive for 5 seconds, send a ping/pong message and wait for 5 more seconds then close the socket.




Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.