listener tcp: Improve reconnect logic to work in after system sleeps and handle more errors
This commit is contained in:
parent
f2a89c29df
commit
2c98cf1acd
|
@ -29,7 +29,7 @@ namespace SparkleLib {
|
||||||
private Object socket_lock = new Object ();
|
private Object socket_lock = new Object ();
|
||||||
private bool is_connected = false;
|
private bool is_connected = false;
|
||||||
private bool is_connecting = false;
|
private bool is_connecting = false;
|
||||||
private int receive_timeout = 180 * 1000;
|
private DateTime last_ping = DateTime.Now;
|
||||||
|
|
||||||
|
|
||||||
public SparkleListenerTcp (Uri server, string folder_identifier) :
|
public SparkleListenerTcp (Uri server, string folder_identifier) :
|
||||||
|
@ -70,9 +70,8 @@ namespace SparkleLib {
|
||||||
lock (this.socket_lock) {
|
lock (this.socket_lock) {
|
||||||
this.socket = new Socket (AddressFamily.InterNetwork,
|
this.socket = new Socket (AddressFamily.InterNetwork,
|
||||||
SocketType.Stream, ProtocolType.Tcp) {
|
SocketType.Stream, ProtocolType.Tcp) {
|
||||||
|
ReceiveTimeout = 5 * 1000,
|
||||||
ReceiveTimeout = this.receive_timeout,
|
SendTimeout = 5 * 1000
|
||||||
SendTimeout = 10 * 1000
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Try to connect to the server
|
// Try to connect to the server
|
||||||
|
@ -99,6 +98,11 @@ namespace SparkleLib {
|
||||||
this.is_connected = false;
|
this.is_connected = false;
|
||||||
this.is_connecting = false;
|
this.is_connecting = false;
|
||||||
|
|
||||||
|
if (this.socket.Connected)
|
||||||
|
this.socket.Shutdown (SocketShutdown.Both);
|
||||||
|
|
||||||
|
this.socket.Dispose ();
|
||||||
|
|
||||||
OnDisconnected (e.Message);
|
OnDisconnected (e.Message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -106,81 +110,94 @@ namespace SparkleLib {
|
||||||
|
|
||||||
byte [] bytes = new byte [4096];
|
byte [] bytes = new byte [4096];
|
||||||
int bytes_read = 0;
|
int bytes_read = 0;
|
||||||
DateTime last_ping = DateTime.Now;
|
|
||||||
|
|
||||||
// Wait for messages
|
// Wait for messages
|
||||||
while (this.is_connected) {
|
while (this.is_connected) {
|
||||||
try {
|
|
||||||
// This blocks the thread
|
|
||||||
bytes_read = this.socket.Receive (bytes);
|
|
||||||
|
|
||||||
// We've timed out, let's ping the server to
|
// This blocks the thread
|
||||||
// see if the connection is still up
|
int i = 0;
|
||||||
} catch (SocketException) {
|
while (this.socket.Available < 1) {
|
||||||
|
Thread.Sleep (1000);
|
||||||
|
Console.WriteLine ("Waiting for available bytes... " + i);
|
||||||
|
i++;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Check when the last ping occured. If it's
|
// We've timed out, let's ping the server to
|
||||||
// significantly longer than our regular interval the
|
// see if the connection is still up
|
||||||
// system likely woke up from sleep and we want to
|
if (i == 60) {
|
||||||
// simulate a disconnect
|
SparkleHelpers.DebugInfo ("ListenerTcp",
|
||||||
int sleepiness = DateTime.Compare (
|
"Pinging " + Server);
|
||||||
last_ping.AddMilliseconds (this.receive_timeout * 1.25),
|
|
||||||
DateTime.Now
|
|
||||||
);
|
|
||||||
|
|
||||||
if (sleepiness <= 0) {
|
byte [] ping_bytes = Encoding.UTF8.GetBytes ("ping\n");
|
||||||
// 10057 means "Socket is not connected"
|
byte [] pong_bytes = new byte [4096];
|
||||||
// TODO: remove debug output
|
|
||||||
Console.WriteLine ("SLEEP OCCURED");
|
lock (this.socket_lock)
|
||||||
throw new SocketException (10057);
|
this.socket.Send (ping_bytes);
|
||||||
|
|
||||||
|
if (this.socket.Receive (pong_bytes) < 1)
|
||||||
|
// 10057 means "Socket is not connected"
|
||||||
|
throw new SocketException (10057);
|
||||||
|
|
||||||
|
SparkleHelpers.DebugInfo ("ListenerTcp",
|
||||||
|
"Received pong from " + Server);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
this.last_ping = DateTime.Now;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Check when the last ping occured. If it's
|
||||||
|
// significantly longer than our regular interval the
|
||||||
|
// system likely woke up from sleep and we want to
|
||||||
|
// simulate a disconnect
|
||||||
|
int sleepiness = DateTime.Compare (
|
||||||
|
this.last_ping.AddMilliseconds (60 * 1000 * 1.2),
|
||||||
|
DateTime.Now
|
||||||
|
);
|
||||||
|
|
||||||
|
if (sleepiness <= 0) {
|
||||||
|
SparkleHelpers.DebugInfo ("ListenerTcp",
|
||||||
|
"System woke up from sleep");
|
||||||
|
|
||||||
|
// 10057 means "Socket is not connected"
|
||||||
|
throw new SocketException (10057);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SparkleHelpers.DebugInfo ("ListenerTcp", "Pinging " + Server);
|
|
||||||
|
|
||||||
byte [] ping_bytes = Encoding.UTF8.GetBytes ("ping\n");
|
|
||||||
byte [] pong_bytes = new byte [4096];
|
|
||||||
|
|
||||||
lock (this.socket_lock)
|
|
||||||
this.socket.Send (ping_bytes);
|
|
||||||
|
|
||||||
|
|
||||||
this.socket.ReceiveTimeout = 10 * 1000;
|
|
||||||
|
|
||||||
if (this.socket.Receive (pong_bytes) < 1)
|
|
||||||
// 10057 means "Socket is not connected"
|
|
||||||
throw new SocketException (10057);
|
|
||||||
|
|
||||||
SparkleHelpers.DebugInfo ("ListenerTcp", "Received pong from " + Server);
|
|
||||||
|
|
||||||
|
|
||||||
this.socket.ReceiveTimeout = this.receive_timeout;
|
|
||||||
last_ping = DateTime.Now;
|
|
||||||
|
|
||||||
// The ping failed: disconnect completely
|
// The ping failed: disconnect completely
|
||||||
} catch (SocketException) {
|
} catch (SocketException) {
|
||||||
this.is_connected = false;
|
this.is_connected = false;
|
||||||
this.is_connecting = false;
|
this.is_connecting = false;
|
||||||
this.socket.ReceiveTimeout = this.receive_timeout;
|
|
||||||
|
if (this.socket.Connected)
|
||||||
|
this.socket.Shutdown (SocketShutdown.Both);
|
||||||
|
|
||||||
|
this.socket.Dispose ();
|
||||||
|
|
||||||
OnDisconnected ("Ping timeout");
|
OnDisconnected ("Ping timeout");
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (this.socket.Available > 0)
|
||||||
|
lock (this.socket_lock)
|
||||||
|
bytes_read = this.socket.Receive (bytes);
|
||||||
|
|
||||||
|
|
||||||
// Parse the received message
|
// Parse the received message
|
||||||
if (bytes_read > 0) {
|
if (bytes_read > 0) {
|
||||||
string received = Encoding.UTF8.GetString (bytes);
|
string received = Encoding.UTF8.GetString (bytes);
|
||||||
string line = received.Substring (0, received.IndexOf ("\n"));
|
string line = received.Substring (0, received.IndexOf ("\n"));
|
||||||
|
|
||||||
if (!line.Contains ("!"))
|
if (!line.Contains ("!"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
string folder_identifier = line.Substring (0, line.IndexOf ("!"));
|
string folder_identifier = line.Substring (0, line.IndexOf ("!"));
|
||||||
string message = CleanMessage (line.Substring (line.IndexOf ("!") + 1));
|
string message = CleanMessage (line.Substring (line.IndexOf ("!") + 1));
|
||||||
|
|
||||||
if (!folder_identifier.Equals ("debug") &&
|
if (!folder_identifier.Equals ("debug") &&
|
||||||
!String.IsNullOrEmpty (message)) {
|
!String.IsNullOrEmpty (message)) {
|
||||||
|
|
||||||
// We have a message!
|
// We have a message!
|
||||||
OnAnnouncement (new SparkleAnnouncement (folder_identifier, message));
|
OnAnnouncement (new SparkleAnnouncement (folder_identifier, message));
|
||||||
}
|
}
|
||||||
|
@ -201,6 +218,8 @@ namespace SparkleLib {
|
||||||
lock (this.socket_lock)
|
lock (this.socket_lock)
|
||||||
this.socket.Send (Encoding.UTF8.GetBytes (to_send));
|
this.socket.Send (Encoding.UTF8.GetBytes (to_send));
|
||||||
|
|
||||||
|
this.last_ping = DateTime.Now;
|
||||||
|
|
||||||
} catch (SocketException e) {
|
} catch (SocketException e) {
|
||||||
this.is_connected = false;
|
this.is_connected = false;
|
||||||
this.is_connecting = false;
|
this.is_connecting = false;
|
||||||
|
@ -219,6 +238,8 @@ namespace SparkleLib {
|
||||||
lock (this.socket_lock)
|
lock (this.socket_lock)
|
||||||
this.socket.Send (Encoding.UTF8.GetBytes (to_send));
|
this.socket.Send (Encoding.UTF8.GetBytes (to_send));
|
||||||
|
|
||||||
|
this.last_ping = DateTime.Now;
|
||||||
|
|
||||||
} catch (SocketException e) {
|
} catch (SocketException e) {
|
||||||
this.is_connected = false;
|
this.is_connected = false;
|
||||||
this.is_connecting = false;
|
this.is_connecting = false;
|
||||||
|
|
Loading…
Reference in a new issue