示例#1
0
        protected virtual void Dispose(bool disposing)
        {
            _output.CompleteWriter();
            _output.CompleteReader();

            _input.CompleteWriter();
            _input.CompleteReader();
        }
        public async Task WriteLargeDataBinary(int length)
        {
            byte[] data = new byte[length];
            new Random(length).NextBytes(data);
            using (var memoryPool = new MemoryPool())
            {
                var readerWriter = new PipelineReaderWriter(memoryPool);

                var output = readerWriter.Alloc();
                output.Write(data);
                var foo = output.Memory.IsEmpty; // trying to see if .Memory breaks
                await output.FlushAsync();

                readerWriter.CompleteWriter();

                int offset = 0;
                while (true)
                {
                    var result = await readerWriter.ReadAsync();

                    var input = result.Buffer;
                    if (input.Length == 0)
                    {
                        break;
                    }

                    Assert.True(input.Equals(new Span <byte>(data, offset, input.Length)));
                    offset += input.Length;
                    readerWriter.Advance(input.End);
                }
                Assert.Equal(data.Length, offset);
            }
        }
        public async Task WriteLargeDataTextUtf8(int length)
        {
            string data = new string('#', length);

            FillRandomStringData(data, length);
            using (var memoryPool = new MemoryPool())
            {
                var readerWriter = new PipelineReaderWriter(memoryPool);

                var output = readerWriter.Alloc();
                output.Append(data, TextEncoding.Utf8);
                var foo = output.Memory.IsEmpty; // trying to see if .Memory breaks
                await output.FlushAsync();

                readerWriter.CompleteWriter();

                int offset = 0;
                while (true)
                {
                    var result = await readerWriter.ReadAsync();

                    var input = result.Buffer;
                    if (input.Length == 0)
                    {
                        break;
                    }

                    string s = ReadableBufferExtensions.GetUtf8String(input);
                    Assert.Equal(data.Substring(offset, input.Length), s);
                    offset += input.Length;
                    readerWriter.Advance(input.End);
                }
                Assert.Equal(data.Length, offset);
            }
        }
        public async Task WriteLargeDataBinary(int length)
        {
            byte[] data = new byte[length];
            new Random(length).NextBytes(data);
            using (var memoryPool = new MemoryPool())
            {
                var readerWriter = new PipelineReaderWriter(memoryPool);

                var output = readerWriter.Alloc();
                output.Write(data);
                var foo = output.Memory.IsEmpty; // trying to see if .Memory breaks
                await output.FlushAsync();
                readerWriter.CompleteWriter();

                int offset = 0;
                while (true)
                {
                    var result = await readerWriter.ReadAsync();
                    var input = result.Buffer;
                    if (input.Length == 0) break;

                    Assert.True(input.Equals(new Span<byte>(data, offset, input.Length)));
                    offset += input.Length;
                    readerWriter.Advance(input.End);
                }
                Assert.Equal(data.Length, offset);
            }
        }
示例#5
0
        /// <summary>
        /// Releases all resources owned by the connection
        /// </summary>
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                _output.CompleteWriter();
                _output.CompleteReader();

                _input.CompleteWriter();
                _input.CompleteReader();

                GC.SuppressFinalize(this);
                _socket?.Dispose();
                _socket = null;
                if (_ownsFactory)
                {
                    _factory?.Dispose();
                }
                _factory = null;
            }
        }
        public void ReceiveBeginComplete(uint bytesTransferred)
        {
            if (bytesTransferred == 0 || _input.Writing.IsCompleted)
            {
                _input.CompleteWriter();
            }
            else
            {
                _buffer.Advance((int)bytesTransferred);
                _buffer.Commit();

                ProcessReceives();
            }
        }
示例#7
0
 public void Complete(Exception exception = null)
 {
     _readerWriter.CompleteWriter(exception);
 }
示例#8
0
 public void FinishWriting() => _readerWriter.CompleteWriter();
示例#9
0
        private async void ReceiveFromSocketAndPushToWriterAsync()
        {
            SocketAsyncEventArgs args = null;

            try
            {
                // if the consumer says they don't want the data, we need to shut down the receive
                GC.KeepAlive(_input.Writing.ContinueWith(delegate
                {// GC.KeepAlive here just to shut the compiler up
                    try { Socket.Shutdown(SocketShutdown.Receive); } catch { }
                }));

                // wait for someone to be interested in data before we
                // start allocating buffers and probing the socket
                await _input.ReadingStarted;

                args = GetOrCreateSocketAsyncEventArgs();
                while (!_input.Writing.IsCompleted)
                {
                    bool           haveWriteBuffer = false;
                    WritableBuffer buffer          = default(WritableBuffer);
                    var            initialSegment  = default(ArraySegment <byte>);

                    try
                    {
                        int bytesFromInitialDataBuffer = 0;

                        if (Socket.Available == 0)
                        {
                            // now, this gets a bit messy unfortunately, because support for the ideal option
                            // (zero-length reads) is platform dependent
                            switch (_bufferStyle)
                            {
                            case BufferStyle.Unknown:
                                try
                                {
                                    initialSegment = await ReceiveInitialDataUnknownStrategyAsync(args);
                                }
                                catch
                                {
                                    initialSegment = default(ArraySegment <byte>);
                                }
                                if (initialSegment.Array == null)
                                {
                                    continue;     // redo from start
                                }
                                break;

                            case BufferStyle.UseZeroLengthBuffer:
                                // if we already have a buffer, use that (but: zero count); otherwise use a shared
                                // zero-length; this avoids constantly changing the buffer that the args use, which
                                // avoids some overheads
                                args.SetBuffer(args.Buffer ?? _zeroLengthBuffer, 0, 0);

                                // await async for the io work to be completed
                                await Socket.ReceiveSignalAsync(args);

                                break;

                            case BufferStyle.UseSmallBuffer:
                                // We need  to do a speculative receive with a *cheap* buffer while we wait for input; it would be *nice* if
                                // we could do a zero-length receive, but this is not supported equally on all platforms (fine on Windows, but
                                // linux hates it). The key aim here is to make sure that we don't tie up an entire block from the memory pool
                                // waiting for input on a socket; fine for 1 socket, not so fine for 100,000 sockets

                                // do a short receive while we wait (async) for data
                                initialSegment = LeaseSmallBuffer();
                                args.SetBuffer(initialSegment.Array, initialSegment.Offset, initialSegment.Count);

                                // await async for the io work to be completed
                                await Socket.ReceiveSignalAsync(args);

                                break;
                            }
                            if (args.SocketError != SocketError.Success)
                            {
                                throw new SocketException((int)args.SocketError);
                            }

                            // note we can't check BytesTransferred <= 0, as we always
                            // expect 0; but if we returned, we expect data to be
                            // buffered *on the socket*, else EOF
                            if ((bytesFromInitialDataBuffer = args.BytesTransferred) <= 0)
                            {
                                if (ReferenceEquals(initialSegment.Array, _zeroLengthBuffer))
                                {
                                    // sentinel value that means we should just
                                    // consume sync (we expect there to be data)
                                    initialSegment = default(ArraySegment <byte>);
                                }
                                else
                                {
                                    // socket reported EOF
                                    RecycleSmallBuffer(ref initialSegment);
                                }
                                if (Socket.Available == 0)
                                {
                                    // yup, definitely an EOF
                                    break;
                                }
                            }
                        }


                        // note that we will try to coalesce things here to reduce the number of flushes; we
                        // certainly want to coalesce the initial buffer (from the speculative receive) with the initial
                        // data, but we probably don't want to buffer indefinitely; for now, it will buffer up to 4 pages
                        // before flushing (entirely arbitrarily) - might want to make this configurable later
                        buffer          = _input.Alloc(SmallBufferSize * 2);
                        haveWriteBuffer = true;

                        const int FlushInputEveryBytes = 4 * MemoryPool.MaxPooledBlockLength;

                        if (initialSegment.Array != null)
                        {
                            // need to account for anything that we got in the speculative receive
                            if (bytesFromInitialDataBuffer != 0)
                            {
                                buffer.Write(new Span <byte>(initialSegment.Array, initialSegment.Offset, bytesFromInitialDataBuffer));
                            }
                            // make the small buffer available to other consumers
                            RecycleSmallBuffer(ref initialSegment);
                        }

                        bool isEOF = false;
                        while (Socket.Available != 0 && buffer.BytesWritten < FlushInputEveryBytes)
                        {
                            buffer.Ensure(); // ask for *something*, then use whatever is available (usually much much more)
                            SetBuffer(buffer.Memory, args);
                            // await async for the io work to be completed
                            await Socket.ReceiveSignalAsync(args);

                            // either way, need to validate
                            if (args.SocketError != SocketError.Success)
                            {
                                throw new SocketException((int)args.SocketError);
                            }
                            int len = args.BytesTransferred;
                            if (len <= 0)
                            {
                                // socket reported EOF
                                isEOF = true;
                                break;
                            }

                            // record what data we filled into the buffer
                            buffer.Advance(len);
                        }
                        if (isEOF)
                        {
                            break;
                        }
                    }
                    finally
                    {
                        RecycleSmallBuffer(ref initialSegment);
                        if (haveWriteBuffer)
                        {
                            await buffer.FlushAsync();
                        }
                    }
                }
                _input.CompleteWriter();
            }
            catch (Exception ex)
            {
                // don't trust signal after an error; someone else could
                // still have it and invoke Set
                if (args != null)
                {
                    args.UserToken = null;
                }
                _input?.CompleteWriter(ex);
            }
            finally
            {
                RecycleSocketAsyncEventArgs(args);
            }
        }
        public async Task WriteLargeDataTextUtf8(int length)
        {
            string data = new string('#', length);
            FillRandomStringData(data, length);
            using (var memoryPool = new MemoryPool())
            {
                var readerWriter = new PipelineReaderWriter(memoryPool);

                var output = readerWriter.Alloc();
                output.Append(data, TextEncoding.Utf8);
                var foo = output.Memory.IsEmpty; // trying to see if .Memory breaks
                await output.FlushAsync();
                readerWriter.CompleteWriter();

                int offset = 0;
                while (true)
                {
                    var result = await readerWriter.ReadAsync();
                    var input = result.Buffer;
                    if (input.Length == 0) break;

                    string s = ReadableBufferExtensions.GetUtf8String(input);
                    Assert.Equal(data.Substring(offset, input.Length), s);
                    offset += input.Length;
                    readerWriter.Advance(input.End);
                }
                Assert.Equal(data.Length, offset);
            }
        }