/// <summary> /// 连接服务端 /// </summary> /// <param name="info"></param> /// <returns></returns> public async static Task <IChannel> ConnectAsync(DotNettyClientInfo info) { IChannel channel; try { if (!string.IsNullOrEmpty(info.LocalHost) && info.LocalPort != null) { channel = await bootstrap.ConnectAsync(new IPEndPoint(IPAddress.Parse(info.Host), info.Port), new IPEndPoint(IPAddress.Parse(info.LocalHost), info.LocalPort.Value)); } else { channel = await bootstrap.ConnectAsync(new IPEndPoint(IPAddress.Parse(info.Host), info.Port)); } } catch (Exception ex) { if (ex.InnerException != null) { ex = ex.InnerException; } logger.LogError(ex, $"Channel connect failed. Host={info.Host}, Port={info.Port}, LocalHost={info.LocalHost}, LocalPort={info.LocalPort}"); clientInfoList.TryRemove(info.ChannelName, out info); throw ex; } var localIPEndPoint = ((IPEndPoint)channel.LocalAddress); info.LocalHost = localIPEndPoint.Address.ToIPString(); info.LocalPort = localIPEndPoint.Port; info.Channel = channel; var clientInfoAddResult = clientInfoList.TryAdd(info.ChannelName, info); if (!clientInfoAddResult) { logger.LogError($"Channel is exist. Host={info.Host}, Port={info.Port}, LocalHost={info.LocalHost}, LocalPort={info.LocalPort}"); await channel.CloseAsync(); throw new InvalidOperationException("Channel is exist."); } return(channel); }
private static Func <string, Task <LoginRequestData> > CreateGetLoginRequestDataHandler() { return(new Func <string, Task <LoginRequestData> >(async channelName => { DotNettyClientInfo result = null; for (var i = 0; i < 3 && !clientInfoList.TryGetValue(channelName, out result); i++) { await Task.Delay(100); } if (result != null) { return await result.GetLoginRequestDataHandler(); } return new LoginRequestData(); })); }
/// <summary> /// 执行与服务端连接 /// </summary> /// <returns></returns> private async Task DoConnectAsync() { if (Status == ClientStatus.Connected) { return; } if (Status == ClientStatus.Connecting) { logger.LogError($"Client connect has begun. Host={Host}, Port={Port}, LocalHost={LocalHost}, LocalPort={LocalPort}"); throw new InvalidOperationException($"Client connect has begun. Host={Host}, Port={Port}, LocalHost={LocalHost}, LocalPort={LocalPort}"); } Status = ClientStatus.Connecting; logger.LogDebug($"Client connect beginning. Host={Host}, Port={Port}, LocalHost={LocalHost}, LocalPort={LocalPort}"); try { var dotNettyClientInfo = new DotNettyClientInfo() { Host = Host, Port = Port, LocalHost = LocalHost, LocalPort = LocalPort, RequestManager = requestManager, InactiveHandler = InactiveHandler, GetLoginRequestDataHandler = GetLoginRequestData, LoginResponseHandler = LoginResponse }; //发起异步连接操作 var oldChannel = channel; channel = await BootstrapManager.ConnectAsync(dotNettyClientInfo); if (oldChannel != null) { await oldChannel.CloseAsync(); } channelName = dotNettyClientInfo.ChannelName; } catch (Exception ex) { Status = ClientStatus.PassiveClosed; logger.LogError(ex, $"Client connect has error. Host={Host}, Port={Port}, LocalHost={LocalHost}, LocalPort={LocalPort}, ExceptionMessage={ex.Message}, ExceptionStackTrace={ex.StackTrace}"); throw new NetworkException(Host, Port, ex.Message); } try { connectTcs = new TaskCompletionSource <object>(); connectCts = new CancellationTokenSource(3000); //登录验证响应超时 var token = connectCts.Token; token.Register(() => { try { connectTcs.SetException(new TimeoutException("Login response timeout.")); } catch { } }); await connectTcs.Task; //等待登录验证响应 } catch (Exception ex) { await CloseAsync(); logger.LogError(ex, $"Client login has error. Host={Host}, Port={Port}, LocalHost={LocalHost}, LocalPort={LocalPort}, ExceptionMessage={ex.Message}, ExceptionStackTrace={ex.StackTrace}"); throw new NetworkException(Host, Port, ex.Message); } finally { connectCts = null; connectTcs = null; } Status = ClientStatus.Connected; logger.LogDebug($"Client connect finished. Host={Host}, Port={Port}, LocalHost={LocalHost}, LocalPort={LocalPort}"); }