private async Task PingProcess() { var pingPacket = _socketSerializer.CreatePingPacket(); if (pingPacket != null) { while (!Disconnected) { // Если никакого входящего if ((DateTime.UtcNow - LastReadData).TotalSeconds > _socket.PingTimeOut) { await Send(pingPacket); // Ожидаем то что Ping пакет уйдет и придет ответ await Task.Delay(_socket.PacketDeliveryTimeOut * 1000); var now = DateTime.UtcNow; var seconds = (now - LastReadData).TotalSeconds; // Если за это время ответ на Ping не пришел, считаем что что связи нет и ее можно рвать if (seconds > _socket.PingTimeOut) { _log.Add($"{_socket.SocketName}: Ping detected invalid connection:{Id}. Disconnect"); Disconnect(); break; } } await Task.Delay(_socket.PingTimeOut); } } }
private async Task ReadThread() { try { var stream = _socket.GetStream(); while (!Disconnected) { var tcpData = await _tcpSerializer.Deserialize(stream); _socketStatistic.LastRecieveTime = DateTime.UtcNow; _socketStatistic.Recieved += tcpData.Item2; if (tcpData.Item1 != null) { await TcpService.HandleDataFromSocket(tcpData.Item1); } } } catch (Exception exception) { await Disconnect(); _log.Add("Error ReadData [" + Id + "]:" + exception.Message); } }
private async void SocketThread() { while (_working) { try { using (var connection = await Connect()) { var readTask = Task.Factory.StartNew(connection.StartReadData, TaskCreationOptions.LongRunning).Unwrap(); var pingTask = Task.Factory.StartNew(() => SocketPingProcess(connection), TaskCreationOptions.LongRunning).Unwrap(); await Task.WhenAny(readTask, pingTask); } } catch (SocketException se) { if (se.SocketErrorCode == SocketError.ConnectionRefused) { _log?.Error(se, "Connection support exception"); _legacyLog?.Add("Connection support exception: " + se.Message); } } catch (Exception ex) { _log?.Error(ex, "Connection support fatal exception"); _legacyLog?.Add("Connection support fatal exception:" + ex.Message); } finally { _service = default(TService); _log?.Warning("Connection timeout..."); _legacyLog?.Add("Connection Timeout..."); Thread.Sleep(_reconnectTimeOut); } } }
public async Task Disconnect(Exception exc) { try { // Вычитаем состояние дисконнект в одном потоке и сменим состояние в Disconnect=true bool disconnected; lock (_disconnectLock) { disconnected = Disconnected; Disconnected = true; } // Если вычитанное состояние не было дисконнект- почистим все что необхдимо почистить if (!disconnected) { // Если серверная служба следит за тем что сокет дисконнектнулся - сообщим об этом DisconnectAction?.Invoke(this); _socketStatistic.LastDisconnectionTime = DateTime.UtcNow; _log?.Info("Disconnected", new { connectionId = Id }); _legacyLog?.Add("Disconnected[" + Id + "]"); if (_tcpService is ISocketNotifier socketNotifier) { await socketNotifier.Disconnect(exc); } (_tcpService as IDisposable)?.Dispose(); } _socket.Dispose(); } catch (Exception exception) { _log?.Error(exception, "Disconnection error", new { connectionId = Id }); _legacyLog?.Add("Disconnect error. Id=" + Id + "; Msg:" + exception.Message); } }
public void AcceptSocketThread() { _serverSocket = new TcpListener(_ipEndPoint); _serverSocket.Start(); Log.Add("Started listening tcp socket: " + _ipEndPoint.Port); while (_thread != null) { try { var acceptedSocket = _serverSocket.AcceptTcpClient(); var service = _srvFactory(); var connection = new TcpConnection(service, new TSerializer(), acceptedSocket, SocketStatistic, Log, _id++); _connections.AddSocket(connection); connection.StartReadData(); } catch (Exception ex) { Log.Add("Error accepting socket: " + ex.Message); } } }
public void AddSocket(TcpConnection connection) { _lockSlim.EnterWriteLock(); try { connection.DisconnectAction = RemoveSocket; _sockets.Add(connection.Id, connection); } finally { _lockSlim.ExitWriteLock(); } _log.Add("Socket Accepted. Id=" + connection.Id.ToString(CultureInfo.InvariantCulture)); }
public async Task SocketThread() { while (_working) { try { // Пытаемся создать соединение с сервером var connection = await Connect(); _socketLog.Add($"Connected to server:{_ipEndPoint}. Id:{connection.Id}"); _serializer.Init(); // Запускаем процесс чтения данных. Он должен отвалиться сам когда потеряется связь await connection.ReadThread(); } catch (Exception ex) { _socketLog.Add("Socket Thread Excepion: " + ex.Message); } await Task.Delay(_reconnectTimeOut); } }
// Метод, который пытается сделать соединение с сервером private async Task <TcpConnection> Connect() { _log?.Add("Attempt To Connect:" + _ipEndPoint.Address + ":" + _ipEndPoint.Port); var tcpClient = new TcpClient(); await tcpClient.ConnectAsync(_ipEndPoint.Address, _ipEndPoint.Port); _service = _srvFactory(); SocketStatistic.Init(); var connection = new TcpConnection(_service, new TTcpSerializer(), tcpClient, SocketStatistic, _log, _id++); _log?.Add("Connected. Id=" + connection.Id); return(connection); }
public void HandleDataFromSocket(object data) { try { switch (data) { case TheResponseModel theResponse: _log?.Info("Response", new { processId = theResponse.ProcessId, responseType = theResponse.GetType() }); _legacyLog?.Add($"Response ProcessId: {theResponse.ProcessId}"); _tasksManager.SetResult(theResponse.ProcessId, theResponse); break; case TheNewResponseModel theNewResponse: _log?.Info("Response", new { processId = theNewResponse.Id, responseType = theNewResponse.GetType() }); _legacyLog?.Add($"Response Id: {theNewResponse.Id}"); _newTasksManager.SetResult(theNewResponse.Id, theNewResponse); break; case MarketOrderResponseModel theMarketOrderResponse: _log?.Info("Response", new { processId = theMarketOrderResponse.Id, responseType = theMarketOrderResponse.GetType() }); _legacyLog?.Add($"Response Id: {theMarketOrderResponse.Id}"); _marketOrdersTasksManager.SetResult(theMarketOrderResponse.Id, theMarketOrderResponse); break; case MeMultiLimitOrderResponseModel multiLimitOrderResponse: _log?.Info("Response", new { processId = multiLimitOrderResponse.Id, responseType = multiLimitOrderResponse.GetType() }); _legacyLog?.Add($"Response Id: {multiLimitOrderResponse.Id}"); _multiOrdersTasksManager.SetResult(multiLimitOrderResponse.Id, multiLimitOrderResponse); break; // No handlers for the following messages case MePingModel m0: case MeCashInOutModel m1: case MeLimitOrderModel m2: case MeMarketOrderObsoleteModel m3: case MeLimitOrderCancelModel m4: case MeUpdateBalanceModel m5: case MeNewTransferModel m6: case MeNewCashInOutModel m7: case MeNewSwapModel m8: case MeUpdateWalletCredsModel m9: case MeNewLimitOrderModel m10: case MeNewLimitOrderCancelModel m11: case MeNewMarketOrderModel m12: case MeMarketOrderModel m13: case MeNewUpdateBalanceModel m14: case MeMultiLimitOrderModel m15: case MeMultiLimitOrderCancelModel m16: case MeNewUpdateReservedBalanceModel m17: break; default: throw new ArgumentException(nameof(data), $"{data.GetType().Name} is not mapped. Please check the mapping in the MatchingEngineSerializer class"); } } catch (KeyNotFoundException exception) { _log?.Error(exception, context: data); if (_ignoreErrors) { _legacyLog?.Add($"Response: {data.ToJson()}"); _legacyLog?.Add(exception.ToString()); } else { throw; } } }