/// <summary> /// Send the given data to the server using the established connection /// </summary> /// <param name="data">The data to send to the server</param> /// <param name="numAttempts">The number of times a send has already been tried</param> /// <returns>True if the send succeeds.</returns> private async Task <bool> Send(string data, int numAttempts) { PrintLine(); // initialize some values bool timerPopped = false; Task <bool> awaitable = null; System.Diagnostics.Debug.WriteLine(String.Format(">> {0} [{1}]", data, numAttempts)); // check the number of attempts if (numAttempts >= MAX_SEND_ATTEMPS) { var e = new TimeoutException("Too many attempts to send \"" + data + "\" to remote server"); FatalException(this, new FatalEventArgs( ExceptionType.SEND_FAILED, e)); throw e; } // We are re-using the _socket object initialized in the Connect method if (_socket == null || _dataWriter == null) { var e = new NullReferenceException( "Socket is null while attempting to send message \"" + data + "\""); NonFatalException(this, new NonFatalEventArgs( ExceptionType.SEND_RECEIVE_NO_SOCKET, e)); throw e; } // Write the string. // Writing data to the writer will just store data in memory. if (numAttempts == 0) { _dataWriter.WriteUInt32(Convert.ToUInt32(data.Length)); _dataWriter.WriteString(data); } // attempt to write the data try { // Write the locally buffered data to the network. var timer = new AwaitTimer(3000); timerPopped = !timer.timeTask(_dataWriter.StoreAsync()); } catch (Exception e) { if (e.Message == CONNECTION_CLOSED_REMOTELY) { // close the socket Close(); FatalException(this, new FatalEventArgs( ExceptionType.RECEIVE_FAILED, e)); throw e; } else if (SocketError.GetStatus(e.HResult) == SocketErrorStatus.Unknown) { // If this is an unknown status it means that the error if fatal and retry will likely fail. FatalException(this, new FatalEventArgs( ExceptionType.SEND_FAILED, e)); throw; } else { NonFatalException(this, new NonFatalEventArgs( ExceptionType.SEND_FAILED, e)); // attempt to send again awaitable = Send(data, numAttempts + 1); } } // wait for tasks to finish if (awaitable != null) { await awaitable; } // did the timer pop before the send could be completed? if (timerPopped) { throw new TimeoutException("Timeout on sending"); } return(true); }
/// <summary> /// Attempt a TCP socket connection to the given host over the given port /// </summary> /// <param name="hostName">The name of the host</param> /// <param name="portNumber">The port number to connect</param> /// <param name="numAttempts">The number of times a connection has already been tried</param> /// <returns>True if the connection succeeds</returns> private async Task <bool> Connect(string hostName, int portNumber, int numAttempts) { PrintLine(); System.Diagnostics.Debug.WriteLine(String.Format("connecting: {0}, {1}, {2}", hostName, portNumber, numAttempts)); string result = string.Empty; lastHostName = hostName; lastPortNumber = portNumber; // check the number of attempts if (numAttempts >= MAX_CONNECT_ATTEMPTS) { PrintLine(); var e = new TimeoutException("Too many attempts to connect to remote server"); FatalException(this, new FatalEventArgs( ExceptionType.CONNECTION_NOT_ESTABLISHED, e)); throw e; } // initialize some values Task <bool> awaitable = null; StreamSocket newSocket = new StreamSocket(); bool timerPopped = false; // connect to the remote end try { var timer = new AwaitTimer(3000); timerPopped = !timer.timeTask(newSocket.ConnectAsync( new HostName(hostName), portNumber.ToString(), SocketProtectionLevel.PlainSocket)); } catch (ArgumentException e) { NonFatalException(this, new NonFatalEventArgs( ExceptionType.HOSTNAME_INVALID, e)); // attempt to reconnect awaitable = Connect(hostName, portNumber, numAttempts + 1); } catch (Exception e) { // If this is an unknown status it means that the error is fatal and retry will likely fail. if (SocketError.GetStatus(e.HResult) == SocketErrorStatus.Unknown) { PrintLine(); FatalException(this, new FatalEventArgs( ExceptionType.CONNECTION_NOT_ESTABLISHED, e)); throw; } else { NonFatalException(this, new NonFatalEventArgs( ExceptionType.CONNECTION_NOT_ESTABLISHED, e)); // attempt to reconnect awaitable = Connect(hostName, portNumber, numAttempts + 1); } } // wait for all async connection attempts if (awaitable != null) { await awaitable; } // did the timer pop? throw an error! if (timerPopped) { PrintLine(); newSocket.Dispose(); throw new TimeoutException("Timeout on connecting"); } // Check that the socket doesn't already exist if (_socket != null) { Close(); } // establish the socket _socket = newSocket; _dataWriter = new DataWriter(_socket.OutputStream); _dataReader = new DataReader(_socket.InputStream); activeListenerIDs.Add(activeListenerIDs.Count, true); // send/receive the alignment messages and // listen for incoming messages ListenForMessages(null, null, activeListenerIDs.Count - 1); PrintLine(); System.Diagnostics.Debug.WriteLine("new socket: " + newSocket); return(true); }