コード例 #1
0
            async Task <Result> ClientSingleConnectionAsync(Direction dir, AsyncManualResetEvent fireMeWhenReady, CancellationToken cancel)
            {
                Result             ret  = new Result();
                AsyncCleanuperLady lady = new AsyncCleanuperLady();

                try
                {
                    var tcp = new FastPalTcpProtocolStub(lady, cancel: cancel);

                    var sock = await tcp.ConnectAsync(ServerIP, ServerPort, cancel, ConnectTimeout);

                    var app = sock.GetFastAppProtocolStub();

                    var attachHandle = app.AttachHandle;

                    var st = app.GetStream();

                    if (dir == Direction.Recv)
                    {
                        app.AttachHandle.SetStreamReceiveTimeout(RecvTimeout);
                    }

                    try
                    {
                        var hello = await st.ReceiveAllAsync(16);

                        Dbg.Where();
                        if (Encoding.ASCII.GetString(hello.Span).StartsWith("TrafficServer\r\n") == false)
                        {
                            throw new ApplicationException("Target server is not a Traffic Server.");
                        }
                        Dbg.Where();

                        //throw new ApplicationException("aaaa" + dir.ToString());

                        fireMeWhenReady.Set();

                        cancel.ThrowIfCancellationRequested();

                        await WebSocketHelper.WaitObjectsAsync(
                            manualEvents : ClientStartEvent.ToSingleArray(),
                            cancels : cancel.ToSingleArray()
                            );

                        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 WebSocketHelper.WaitObjectsAsync(
                                    tasks : st.FastReceiveAsync(totalRecvSize : totalRecvSize).ToSingleArray(),
                                    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 WebSocketHelper.WaitObjectsAsync(
                                        manualEvents: sock.Pipe.OnDisconnectedEvent.ToSingleArray(),
                                        timeout: 200);
                                }
                            });

                            await WhenAll.Await(false, recvResult, sendSurprise);

                            await recvResult;
                        }

                        st.Disconnect();

                        Dbg.Where();
                        return(ret);
                    }
                    catch (Exception ex)
                    {
                        Dbg.Where(ex.Message);
                        ExceptionQueue.Add(ex);
                        throw;
                    }
                }
                finally
                {
                    await lady;
                }
            }
コード例 #2
0
            public async Task <Result> RunClientAsync()
            {
                if (IsServerMode)
                {
                    throw new ApplicationException("Server mode");
                }

                if (Once.IsFirstCall() == false)
                {
                    throw new ApplicationException("You cannot reuse the object.");
                }

                WriteLine("Client mode start");

                ExceptionQueue = new ExceptionQueue();
                SessionId      = WebSocketHelper.RandUInt64();

                List <Task <Result> >        tasks       = new List <Task <Result> >();
                List <AsyncManualResetEvent> readyEvents = new List <AsyncManualResetEvent>();

                AsyncCleanuperLady lady = new AsyncCleanuperLady();

                try
                {
                    CancelWatcher cancelWatcher = new CancelWatcher(lady, this.Cancel);
                    for (int i = 0; i < NumConnection; i++)
                    {
                        Direction dir;
                        if (Mode == ModeFlag.Download)
                        {
                            dir = Direction.Recv;
                        }
                        else if (Mode == ModeFlag.Upload)
                        {
                            dir = Direction.Send;
                        }
                        else
                        {
                            dir = ((i % 2) == 0) ? Direction.Recv : Direction.Send;
                        }

                        AsyncManualResetEvent readyEvent = new AsyncManualResetEvent();
                        var t = ClientSingleConnectionAsync(dir, readyEvent, cancelWatcher.CancelToken);
                        ExceptionQueue.RegisterWatchedTask(t);
                        tasks.Add(t);
                        readyEvents.Add(readyEvent);
                    }

                    try
                    {
                        using (var whenAllReady = new WhenAll(readyEvents.Select(x => x.WaitAsync())))
                        {
                            await WebSocketHelper.WaitObjectsAsync(
                                tasks : tasks.Append(whenAllReady.WaitMe).ToArray(),
                                cancels : cancelWatcher.CancelToken.ToSingleArray(),
                                manualEvents : ExceptionQueue.WhenExceptionAdded.ToSingleArray());
                        }

                        Cancel.ThrowIfCancellationRequested();
                        ExceptionQueue.ThrowFirstExceptionIfExists();

                        ExceptionQueue.WhenExceptionAdded.CallbackList.AddSoftCallback(x =>
                        {
                            cancelWatcher.Cancel();
                        });

                        using (new DelayAction(lady, TimeSpan * 3 + 180 * 1000, x =>
                        {
                            cancelWatcher.Cancel();
                        }))
                        {
                            ClientStartEvent.Set(true);

                            using (var whenAllCompleted = new WhenAll(tasks))
                            {
                                await WebSocketHelper.WaitObjectsAsync(
                                    tasks : whenAllCompleted.WaitMe.ToSingleArray(),
                                    cancels : cancelWatcher.CancelToken.ToSingleArray()
                                    );

                                await whenAllCompleted.WaitMe;
                            }
                        }

                        Result ret = new Result();

                        ret.Span = TimeSpan;

                        foreach (var r in tasks.Select(x => x.Result))
                        {
                            ret.NumBytesDownload += r.NumBytesDownload;
                            ret.NumBytesUpload   += r.NumBytesUpload;
                        }

                        ret.NumBytesTotal = ret.NumBytesUpload + ret.NumBytesDownload;

                        ret.BpsUpload   = (long)((double)ret.NumBytesUpload * 1000.0 * 8.0 / (double)ret.Span * 1514.0 / 1460.0);
                        ret.BpsDownload = (long)((double)ret.NumBytesDownload * 1000.0 * 8.0 / (double)ret.Span * 1514.0 / 1460.0);
                        ret.BpsTotal    = ret.BpsUpload + ret.BpsDownload;

                        return(ret);
                    }
                    catch (Exception ex)
                    {
                        await Task.Yield();

                        ExceptionQueue.Add(ex);
                    }
                    finally
                    {
                        cancelWatcher.Cancel();
                        try
                        {
                            await Task.WhenAll(tasks);
                        }
                        catch { }
                    }

                    ExceptionQueue.ThrowFirstExceptionIfExists();
                }
                finally
                {
                    await lady;
                }

                Dbg.Where();

                return(null);
            }