public static void Create(SocketAsyncEventArgs args) { var token = new MessageSendToken(); token.Args = args; args.UserToken = token; }
/// <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); }
/// <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); } }