async Task <Result> ClientSingleConnectionAsync(Direction dir, AsyncManualResetEvent fireMeWhenReady, CancellationToken cancel) { Result ret = new Result(); using (NetPalTcpProtocolStub tcp = new NetPalTcpProtocolStub(cancel: cancel)) { await tcp.ConnectAsync(ServerIP, ServerPort, cancel, ConnectTimeout); using (ConnSock sock = new ConnSock(tcp)) { NetAppStub app = sock.GetNetAppProtocolStub(); AttachHandle attachHandle = app.AttachHandle; PipeStream st = app.GetStream(); if (dir == Direction.Recv) { app.AttachHandle.SetStreamReceiveTimeout(RecvTimeout); } try { var hello = await st.ReceiveAllAsync(16); if (hello.Span.ToArray()._GetString_Ascii().StartsWith("TrafficServer\r\n") == false) { throw new ApplicationException("Target server is not a Traffic Server."); } //throw new ApplicationException("aaaa" + dir.ToString()); fireMeWhenReady.Set(); cancel.ThrowIfCancellationRequested(); await TaskUtil.WaitObjectsAsync( manualEvents : ClientStartEvent._SingleArray(), cancels : cancel._SingleArray() ); long tickStart = FastTick64.Now; long tickEnd = tickStart + this.TimeSpan; var sendData = new MemoryBuffer <byte>(); sendData.WriteBool8(dir == Direction.Recv); sendData.WriteUInt64(SessionId); sendData.WriteSInt64(TimeSpan); await st.SendAsync(sendData); if (dir == Direction.Recv) { RefInt totalRecvSize = new RefInt(); while (true) { long now = FastTick64.Now; if (now >= tickEnd) { break; } await TaskUtil.WaitObjectsAsync( tasks : st.FastReceiveAsync(totalRecvSize : totalRecvSize)._SingleArray(), timeout : (int)(tickEnd - now), exceptions : ExceptionWhen.TaskException | ExceptionWhen.CancelException); ret.NumBytesDownload += totalRecvSize; } } else { attachHandle.SetStreamReceiveTimeout(Timeout.Infinite); while (true) { long now = FastTick64.Now; if (now >= tickEnd) { break; } /*await WebSocketHelper.WaitObjectsAsync( * tasks: st.FastSendAsync(SendData, flush: true).ToSingleArray(), * timeout: (int)(tick_end - now), * exceptions: ExceptionWhen.TaskException | ExceptionWhen.CancelException);*/ await st.FastSendAsync(SendData, flush : true); } Task recvResult = Task.Run(async() => { var recvMemory = await st.ReceiveAllAsync(8); MemoryBuffer <byte> recvMemoryBuf = recvMemory; ret.NumBytesUpload = recvMemoryBuf.ReadSInt64(); st.Disconnect(); }); Task sendSurprise = Task.Run(async() => { byte[] surprise = new byte[260]; surprise.AsSpan().Fill((byte)'!'); while (true) { await st.SendAsync(surprise); await TaskUtil.WaitObjectsAsync( manualEvents: sock.Pipe.OnDisconnectedEvent._SingleArray(), timeout: 200); } }); await WhenAll.Await(false, recvResult, sendSurprise); await recvResult; } st.Disconnect(); return(ret); } catch (Exception ex) { ExceptionQueue !.Add(ex); throw; } } } }