/// <summary> /// 构建转发连接处理服务 /// </summary> /// <param name="heartbeatLifetime"></param> /// <param name="heartbeatService"></param> /// <returns></returns> private IEnumerable <Task> BuildHeartbeatService(IServiceProvider heartbeatLifetime, HeartbeatService heartbeatService) { foreach (var client in _settings.Clients) { _logger.LogWarning("侦听客户端的连接端口:{0}", client.ClientId); foreach (var rule in client.ForwardRules) { var detail = new ForwardRuleDetail { ClientId = client.ClientId, ClientKey = client.ClientKey, RuleId = rule.RuleId, ListenerPort = rule.ListenerPort }; var rcs = heartbeatLifetime.GetRequiredService <RequestConnectionService>(); rcs.RequestConnectionEvent += GetRequestConnectionEventHandle(heartbeatService, detail); yield return(rcs.Start(detail.ListenerPort)); _logger.LogWarning("侦听连接端口:{0}, {1}:{2}", client.ClientId, rule.RuleId, rule.ListenerPort); } } }
/// <summary> /// 获取连接请求处理 委托 /// </summary> /// <param name="heartbeatService"></param> /// <returns></returns> private Func <TcpClient, CancellationToken, Task> GetRequestConnectionEventHandle(HeartbeatService heartbeatService, ForwardRuleDetail forwardRuleDetail) { return(async(tcp, serviceToken) => { var remoteEndPoint = tcp.Client.RemoteEndPoint; Action EndNotice = null; try { _logger.LogInformation("接收到访问请求:ClientId, {0}:{1}, 访问者:{2}", forwardRuleDetail.ClientId, forwardRuleDetail.RuleId, remoteEndPoint); var(serverTcp, EndNotice2) = await heartbeatService.GetRequestTcpClient(serviceToken, forwardRuleDetail); EndNotice = EndNotice2; if (serverTcp == null) { _logger.LogInformation("连接请求失败: 未获得服务端tcp连接"); return; } using (var forwarder = new Forwarder(tcp, serverTcp)) { await forwarder.Start(); } } catch (IOException ex) { _logger.LogInformation("数据转发连接断开:ClientId, {0}:{1}, 访问者:{2}, {3}", forwardRuleDetail.ClientId, forwardRuleDetail.RuleId, remoteEndPoint, ex.Message); } catch (Exception ex) { _logger.LogError(ex, "数据转发出现异常:ClientId, {0}:{1}, 访问者:{2}", forwardRuleDetail.ClientId, forwardRuleDetail.RuleId, remoteEndPoint); } EndNotice?.Invoke(); }); }
/// <summary> /// 获取客户端连接 /// </summary> /// <param name="token"></param> /// <returns></returns> public async Task <(TcpClient RequestTcpClient, Action EndNotice)> GetRequestTcpClient(CancellationToken token, ForwardRuleDetail forwardRuleDetail) { var forwardId = Guid.NewGuid().ToString("n"); var tcp = _heartbeatTcpClients.FirstOrDefault(u => u.ClientId == forwardRuleDetail.ClientId); var result = default(TcpClient); var tcsEndNotice = new TaskCompletionSource <TcpClient>(); if (tcp != null) { var tcs = new TaskCompletionSource <TcpClient>(); var cacheKey = $"/CancellationToken/{forwardId}"; var requestInfo = new ForwardRequesInfo { CompletionSource = tcs, EndNotice = tcsEndNotice.Task }; _cache.Set(cacheKey, requestInfo, TimeSpan.FromSeconds(20)); var message = $"connection:{forwardId},{forwardRuleDetail.RuleId}"; var buff = Encoding.ASCII.GetBytes(message); _logger.LogInformation("请求连接客户端连接, 回复客户端消息:{0}", message); await tcp.TcpClient.GetStream().WriteAsync(buff, 0, buff.Length, token).TimeoutAfter(TimeSpan.FromMilliseconds(_sendTimeout), token);; _logger.LogInformation("请求连接客户端连接, 回复客户端消息:{0}, 成功", message); await Task.WhenAny(tcs.Task.ContinueWith(t => { result = t.Result; }), Task.Delay(10 * 1000, token)); } return(result, () => tcsEndNotice.SetResult(result)); }