public override void ConnectToServer() { if (CanConnect) { CanConnect = false; _tcpClient.AutoReconnect = EnableAutoReconnect; _tcpClient.ConnectAsync("127.0.0.1", _serverPort, (isConnected) => { CanConnect = !isConnected; }); } }
private void _server_ClientStatusChanged(object sender, ClientStatusChangedEventArgs args) { if (!IsRunning) { return; } long proxyClientID = args.ClientID; if (args.Status == ClientStatus.Connected) { TcpClientEx tcpClient = new TcpClientEx(RawPacketSpliter.Default); tcpClient.Tag = proxyClientID; tcpClient.ClientStatusChanged += TcpClient_ClientStatusChanged; tcpClient.MessageReceived += TcpClient_MessageReceived; tcpClient.ConnectAsync(RemoteIP, (ushort)RemotePort, (isConnected) => { if (isConnected) { bool isOK = _clientDict.TryAdd(proxyClientID, tcpClient); System.Diagnostics.Debug.Assert(isOK, "add new client failed"); } else { _server.CloseClient(proxyClientID); } if (_waitConnDict.ContainsKey(proxyClientID)) { _waitConnDict[proxyClientID].Set(); } }); } else if (args.Status == ClientStatus.Closed) { if (_clientDict.TryRemove(proxyClientID, out TcpClientEx client)) { client.Close(); } } ClientCount = _server.Clients.Count; if (ClientCountChanged != null) { ClientCountChangedEventArgs countChangedArgs = new ClientCountChangedEventArgs() { NewCount = ClientCount }; ClientCountChanged(this, countChangedArgs); } }
/// <summary> /// Runs the client connection asynchronously. /// </summary> /// <returns>The task object representing the asynchronous operation.</returns> public async Task RunAsync() { ///尝试重新连接 bool isReconnected = true; int reconnectTry = -1; do { reconnectTry++; ByteBuffer = new ByteBuffer(); if (ServerTcpClient != null) { // Take accepted connection from listener tcpClient = ServerTcpClient; } else { // Try to connect to remote host var connectTimeout = TimeSpan.FromTicks(ConnectTimeout.Ticks + (MaxConnectTimeout.Ticks - ConnectTimeout.Ticks) / 20 * Math.Min(reconnectTry, 20)); tcpClient = new TcpClientEx(AddressFamily.InterNetwork); tcpClient.ReceiveTimeout = TcpPackConfig.ReceiveTimeout; tcpClient.SendTimeout = TcpPackConfig.SendTimeout; tcpClient.SendBufferSize = TcpPackConfig.SendBufferSize; tcpClient.ReceiveBufferSize = TcpPackConfig.ReceiveBufferSize; Message?.Invoke(this, new AsyncTcpEventArgs("准备连接到服务器" + IPAddress.ToString())); Task connectTask; if (!string.IsNullOrWhiteSpace(HostName)) { connectTask = tcpClient.ConnectAsync(HostName, Port); } else { connectTask = tcpClient.ConnectAsync(IPAddress, Port); } var timeoutTask = Task.Delay(connectTimeout); if (await Task.WhenAny(connectTask, timeoutTask) == timeoutTask) { //此处增加一个连接超时的任务 Message?.Invoke(this, new AsyncTcpEventArgs("连接超时")); OnConnectedTimeout(isReconnected);//连接超时的返回 continue; } try { await connectTask; } catch (Exception ex) { Message?.Invoke(this, new AsyncTcpEventArgs("连接到远程主机时出错", ex)); await timeoutTask; continue; } } reconnectTry = -1; stream = tcpClient.GetStream(); // 读取直到连接关闭。 //只有在读取时才能检测到闭合连接,因此我们需要读取 //永久地,不仅仅是当我们可能使用接收到的数据时。 var networkReadTask = Task.Run(async() => { // 10 KiB should be enough for every Ethernet packet byte[] buffer = new byte[TcpPackConfig.ByteBufferCapacity]; while (true) { int readLength; try { //异步读取有问题 readLength = await stream.ReadAsync(buffer, 0, buffer.Length); } catch (IOException ex) when((ex.InnerException as SocketException)?.ErrorCode == (int)SocketError.OperationAborted) { // Warning: This error code number (995) may change Message?.Invoke(this, new AsyncTcpEventArgs("本地关闭连接", ex)); readLength = -1; } catch (IOException ex) when((ex.InnerException as SocketException)?.ErrorCode == (int)SocketError.ConnectionAborted) { Message?.Invoke(this, new AsyncTcpEventArgs("连接失败", ex)); readLength = -1; } catch (IOException ex) when((ex.InnerException as SocketException)?.ErrorCode == (int)SocketError.ConnectionReset) { Message?.Invoke(this, new AsyncTcpEventArgs("远程重置连接", ex)); readLength = -2; } if (readLength <= 0) { if (readLength == 0) { Message?.Invoke(this, new AsyncTcpEventArgs("远程关闭连接")); } closedTcs.TrySetResult(true); OnClosed(readLength != -1); return; } //此处做处理,数据包要达到 var segment = new ArraySegment <byte>(buffer, 0, readLength); ByteBuffer.Enqueue(segment); await OnReceivedAsync(readLength); } }); closedTcs = new TaskCompletionSource <bool>(); await OnConnectedAsync(isReconnected); // Wait for closed connection await networkReadTask; tcpClient.Close(); isReconnected = true; }while (AutoReconnect && ServerTcpClient == null); }