Beispiel #1
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);
        }
Beispiel #2
0
        /// <summary>
        /// Sends the specified <see cref="Message"/> using the <see cref="Socket"/> socket asynchronously.
        /// </summary>
        /// <param name="message"><see cref="Message"/> to send.</param>
        ///
        /// <exception cref="ObjectDisposedException">The current instance of the <see cref="NetworkManagerAsync"/> is disposed.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="message"/> is null.</exception>
        /// <exception cref="InvalidMessageException"><paramref name="message"/> length greater than <see cref="Message.MaxSize"/>.</exception>
        public void SendMessage(Message message)
        {
            if (Thread.VolatileRead(ref _disposed) == 1)
            {
                throw new ObjectDisposedException(null, "Cannot SendMessage because the NetworkManagerAsync object was disposed.");
            }
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            var writerStream = new MemoryStream();

            using (var writer = new MessageWriter(writerStream))
            {
                var cipher = _processor.ProcessOutgoing(message);
                if (cipher == null)
                {
                    throw new InvalidOperationException("MessageProcessor failed to process outgoing message.");
                }

                // Make sure the message isn't too large.
                if (cipher.Length > Message.MaxSize)
                {
                    throw new InvalidMessageException("Message size too large.", message);
                }

                var messageLength = BitConverter.GetBytes(cipher.Length);
                if (BitConverter.IsLittleEndian)
                {
                    Array.Reverse(messageLength);
                }

                // Header.
                writer.Write(message.Id);
                writer.Write(messageLength, 1, 3); // Message length
                writer.Write(message.Version);
                // Body encrypted.
                writer.Write(cipher);

                var messageData = writerStream.ToArray();

                var args = _sendPool.Pop();
                if (args == null)
                {
                    Debug.WriteLine("Creating new send operation because pool was empty.");

                    args = new SocketAsyncEventArgs();
                    args.SetBuffer(new byte[65535], 0, 65535);
                    MessageSendToken.Create(args);
                }

                var token = (MessageSendToken)args.UserToken;
                token.Message = message;
                token.Id      = message.Id;
                token.Length  = cipher.Length;
                token.Version = message.Version;
                token.Body    = messageData;

                StartSend(args);
            }
        }