//向客户端发送数据 public void Send(TcpClientEx tcpClient, ArraySegment <byte> datas) { if (tcpClient != null && tcpClient.Connected) { try { NetworkStream stream = tcpClient.GetStream(); if (stream != null) { int num = 0; while (!stream.CanWrite && tcpClient != null && tcpClient.Connected) { num++; if (num > 10) { return; } Thread.Sleep(1000); continue; } SplitPakeage splitPakeage = new SplitPakeage(); byte[] newData = splitPakeage.AssembleBytes(datas, this); stream.WriteAsync(newData, 0, newData.Length); stream.Flush(); TcpPackConfig.SendDelayTime(); } } catch { } } }
/// <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); }