private void SendItem(ReceiveSendItem item) { SocketAsyncEventArgs args = cache.PopOrCreate(); args.Completed += Send_Completed; SendItem(item, args); }
private void ReceiveItem(ReceiveSendItem item, SocketAsyncEventArgs args) { args.UserToken = item; if (!socket.ReceiveAsync(args)) { Receive_Completed(socket, args); } }
private void SendItem(ReceiveSendItem item, SocketAsyncEventArgs args) { args.UserToken = item; int cplen = Math.Min(args.Count, item.Count); Array.Copy(item.Buffer, item.Offset, args.Buffer, args.Offset, cplen); args.SetBuffer(args.Offset, cplen); if (!socket.SendAsync(args)) { Send_Completed(socket, args); } }
private bool TryDequeue(out ReceiveSendItem item) { if (realtimeQueue.TryDequeue(out item)) { return(true); } if (backgroundQueue.TryDequeue(out item)) { return(true); } return(false); }
private void Receive_Completed(object sender, SocketAsyncEventArgs e) { ReceiveSendItem item = (ReceiveSendItem)e.UserToken; if (e.SocketError == SocketError.Shutdown || e.SocketError == SocketError.OperationAborted) { item.Tcs.SetResult(false); RecycleReceive(e); return; } else if (e.SocketError != SocketError.Success) { item.Tcs.SetResult(false); RecycleReceive(e); exhandler.CloseConnection(e.SocketError, e.LastOperation); return; } if (e.BytesTransferred == 0) { item.Tcs.SetResult(false); RecycleReceive(e); exhandler.CloseConnection(SocketError.Disconnecting, e.LastOperation); return; } ReceivedBytes += e.BytesTransferred; // for statistics int cplen = Math.Min(e.BytesTransferred, item.Count); Array.Copy(e.Buffer, e.Offset, item.Buffer, item.Offset, cplen); item.Offset += cplen; item.Count -= cplen; if (item.Count > 0) { ReceiveItem(item, e); } else if (e.BytesTransferred - cplen > 0) { e.SetBuffer(e.Offset + cplen, e.BytesTransferred - cplen); receiveCache = e; item.Tcs.SetResult(true); // Do not recycle this item now when we cache its buffer } else { item.Tcs.SetResult(true); RecycleReceive(e); } }
private void Send_Completed(object sender, SocketAsyncEventArgs e) { ReceiveSendItem item = (ReceiveSendItem)e.UserToken; if (e.SocketError == SocketError.Shutdown) { item.Tcs.SetResult(false); RecycleSend(e); return; } else if (e.SocketError != SocketError.Success) { item.Tcs.SetResult(false); exhandler.CloseConnection(e.SocketError, e.LastOperation); RecycleSend(e); return; } if (e.BytesTransferred == 0) { item.Tcs.SetResult(false); exhandler.CloseConnection(SocketError.ConnectionReset, e.LastOperation); RecycleSend(e); return; } SentBytes += e.BytesTransferred; // for statistics item.Offset += e.BytesTransferred; item.Count -= e.BytesTransferred; if (item.Count > 0) { SendItem(item, e); } else { item.Tcs.SetResult(true); RecycleSend(e); StartSend(locked: false); } }
/// <summary> /// Sends data to the remote host asynchronously. /// </summary> /// <exception cref="ObjectDisposedException" /> public Task <bool> SendAsync(byte[] buffer, int offset, int count, bool background) { if (disposed) { throw new ObjectDisposedException(GetType().FullName); } if (shutdown) { return(Task.FromResult(false)); } ReceiveSendItem item = new ReceiveSendItem(buffer, offset, count); if (background) { backgroundQueue.Enqueue(item); } else { realtimeQueue.Enqueue(item); } EnsureSend(); return(item.Task); }
/// <summary> /// Receives the specified count of bytes from the remote host asynchronously. This method is not threadsafe! /// </summary> /// <exception cref="ObjectDisposedException" /> public Task <bool> ReceiveAsync(byte[] buffer, int offset, int count) { if (disposed) { throw new ObjectDisposedException(GetType().FullName); } if (shutdown) { return(Task.FromResult(false)); } if (receiveCache != null) { int cplen = Math.Min(receiveCache.Count, count); Array.Copy(receiveCache.Buffer, receiveCache.Offset, buffer, offset, cplen); receiveCache.SetBuffer(receiveCache.Offset + cplen, receiveCache.Count - cplen); offset += cplen; count -= cplen; if (receiveCache.Count == 0) { RecycleReceive(receiveCache); receiveCache = null; } } if (count > 0) { ReceiveSendItem item = new ReceiveSendItem(buffer, offset, count); ReceiveItem(item); return(item.Task); } else { return(Task.FromResult(true)); } }