Exemple #1
0
        private void StartSend(SocketAsyncEventArgs args)
        {
            if (args.SocketError == SocketError.OperationAborted || Thread.VolatileRead(ref _disposed) == 1)
            {
                _sendPool.Push(args);
                return;
            }

            args.Completed += AsyncOperationCompleted;
            var token = (MessageSendToken)args.UserToken;

            // If still we have bytes to send.
            if (token.SendRemaining > 0)
            {
                // If message larger than buffer size.
                if (token.SendRemaining > Settings.BufferSize)
                {
                    Buffer.BlockCopy(token.Body, token.SendOffset, args.Buffer, args.Offset, Settings.BufferSize);
                }
                // Else resize buffer count.
                else
                {
                    Buffer.BlockCopy(token.Body, token.SendOffset, args.Buffer, args.Offset, token.SendRemaining);
                    args.SetBuffer(args.Offset, token.SendRemaining);
                }
            }

            if (!Socket.SendAsync(args))
            {
                ProcessSend(args);
            }
        }
Exemple #2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="NetworkManagerAsyncSettings"/> class
        /// with the specified number of receive operation <see cref="SocketAsyncEventArgs"/> objects
        /// and the specified number of send operation <see cref="SocketAsyncEventArgs"/> objects with
        /// the specified buffer size of each <see cref="SocketAsyncEventArgs"/> object.
        /// </summary>
        /// <param name="receiveCount">Number of receive operation <see cref="SocketAsyncEventArgs"/> objects.</param>
        /// <param name="sendCount">Number of send operation <see cref="SocketAsyncEventArgs"/> objects.</param>
        /// <param name="bufferSize">Buffer size of each <see cref="SocketAsyncEventArgs"/> object.</param>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="bufferSize"/> less than 1.</exception>
        public NetworkManagerAsyncSettings(int receiveCount, int sendCount, int bufferSize)
        {
            if (bufferSize < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(bufferSize), "Buffer size cannot be less than 1.");
            }

            _bufferSize = bufferSize;
            _statistics = new NetworkManagerAsyncStatistics();

            // Don't waste IO threads.
            var concurrentOpsCount = Environment.ProcessorCount * 2;

            _concurrentOps = new Semaphore(concurrentOpsCount, concurrentOpsCount);
            _receivePool   = new SocketAsyncEventArgsPool(receiveCount);
            _sendPool      = new SocketAsyncEventArgsPool(sendCount);
            _bufferManager = new MessageBufferManager(receiveCount, sendCount, bufferSize);

            for (int i = 0; i < ReceiveCount; i++)
            {
                var args = new SocketAsyncEventArgs();
                _bufferManager.SetBuffer(args);
                MessageReceiveToken.Create(args);
                _receivePool.Push(args);
            }

            for (int i = 0; i < SendCount; i++)
            {
                var args = new SocketAsyncEventArgs();
                _bufferManager.SetBuffer(args);
                MessageSendToken.Create(args);
                _sendPool.Push(args);
            }

            _buffers = new Pool <byte[]>(64);
            _args    = new Pool <SocketAsyncEventArgs>(receiveCount + sendCount);
        }
Exemple #3
0
        private void AsyncOperationCompleted(object sender, SocketAsyncEventArgs args)
        {
            // Semaphore timeout.
            const int TIMEOUT = 5000;

            args.Completed -= AsyncOperationCompleted;
            if (Settings._concurrentOps.WaitOne(TIMEOUT))
            {
                // Return the SocketAsyncEventArgs object back to its corresponding pool if
                // the NetworkManagerAsync was disconnected purposely or disposed.
                if (args.SocketError == SocketError.OperationAborted || Thread.VolatileRead(ref _disposed) == 1)
                {
                    switch (args.LastOperation)
                    {
                    case SocketAsyncOperation.Receive:
                        _receivePool.Push(args);
                        break;

                    case SocketAsyncOperation.Send:
                        _sendPool.Push(args);
                        break;
                    }

                    Settings._concurrentOps.Release();
                    return;
                }

                if (args.BytesTransferred == 0 || args.SocketError != SocketError.Success)
                {
                    switch (args.LastOperation)
                    {
                    case SocketAsyncOperation.Receive:
                        _receivePool.Push(args);
                        break;

                    case SocketAsyncOperation.Send:
                        _sendPool.Push(args);
                        break;
                    }

                    Settings._concurrentOps.Release();
                    OnDisconnected(new DisconnectedEventArgs(args.SocketError));
                    return;
                }

                switch (args.LastOperation)
                {
                case SocketAsyncOperation.Receive:
                    ProcessReceive(args);
                    break;

                case SocketAsyncOperation.Send:
                    ProcessSend(args);
                    break;

                default:
                    throw new InvalidOperationException("IMPOSSIBRU! Unexpected SocketAsyncOperation: " + args.LastOperation);
                }

                Settings._concurrentOps.Release();
            }
            else
            {
                Console.WriteLine("Semaphore not responding in time.");
                Debug.WriteLine("Semaphore not responding in time.");

                //TODO: Might want drop connection and release the semaphore.
            }
        }