protected void ReceiveCompleted(SocketAsyncEventArgsExt argz) { try { if (argz.SocketError != SocketError.Success) { //ProgramLog.Debug.Log ("Bytes received: {0}", argz.BytesTransferred); var err = argz.SocketError; receiving = false; recvPool.Put(argz); HandleError(err); } else if (argz.BytesTransferred == 0) { //ProgramLog.Debug.Log ("Clean connection shutdown. {0}", socket.Connected); receiving = false; recvPool.Put(argz); HandleError(SocketError.Disconnecting); } else { var bytes = argz.BytesTransferred; receiving = false; if (kicking) { recvPool.Put(argz); return; } while (!receiving) { recvBytes += bytes; BytesReceived += bytes; ProcessRead(); if (kicking) { receiving = false; break; } var left = recvBuffer.Length - recvBytes; if (left <= 0) { return; } argz.SetBuffer(recvBuffer, recvBytes, left); try { receiving = socket.ReceiveAsync(argz); } catch (ObjectDisposedException) { receiving = false; } if (receiving) { bytes = argz.BytesTransferred; } } if (!receiving) { recvPool.Put(argz); } } } catch (Exception e) { ProgramLog.Log(e, "Exception in connection receive callback"); } }
//#if BANDWIDTH_ANALYSIS // public static int[] packetsPerMessage = new int [255]; // public static long[] bytesPerMessage = new long [255]; //#endif protected bool SendMore(SocketAsyncEventArgsExt args, bool flush = false) { flush |= txBuffer == null; try { var queued = false; var escape = false; while (sendQueue.Count > 0 && txListBytes < 2880 && !escape) { var msg = sendQueue.PopFront(); switch (msg.kind) { case Message.BYTES: { var data = (byte[])msg.content; txList.Add(new ArraySegment <byte>(data)); txListBytes += data.Length; queueSize -= data.Length + ARRAY_OBJECT_OVERHEAD; //ProgramLog.Debug.Log ("{1}: Adding bytes {0}", data.Length, Thread.CurrentThread.IsThreadPoolThread); break; } case Message.SEGMENT: { var len = msg.param; var txc = txList.Count; int wraparound = 0; if (txc > 0 && txList[txc - 1].Array == txBuffer) { var seg = txList[txc - 1]; var nlen = seg.Count + len; var nseg = new ArraySegment <byte>(txBuffer, seg.Offset, Math.Min(nlen, txBuffer.Length - seg.Offset)); //ProgramLog.Debug.Log ("{5}: Coalescing {0}, {1} and {2}, {3} [{4}]", seg.Offset, seg.Count, (txHead + txPrepared) % txBuffer.Length, len, nseg.Count, Thread.CurrentThread.IsThreadPoolThread); txList[txc - 1] = nseg; wraparound = nlen - nseg.Count; } else { var offset = (txHead + txPrepared) % txBuffer.Length; //ProgramLog.Debug.Log ("{2}: Adding segment {0}, {1}", offset, len, Thread.CurrentThread.IsThreadPoolThread); var nseg = new ArraySegment <byte>(txBuffer, offset, Math.Min(len, txBuffer.Length - offset)); txList.Add(nseg); wraparound = len - nseg.Count; } if (wraparound > 0) { txList.Add(new ArraySegment <byte>(txBuffer, 0, wraparound)); } txPrepared += len; txListBytes += len; queueSize -= len; break; } default: { var data = SerializeMessage(msg); txList.Add(data); txListBytes += data.Count; //ProgramLog.Debug.Log ("{1}: Adding custom {0}", data.Count, Thread.CurrentThread.IsThreadPoolThread); escape = true; break; } case Message.KICK: { if ((!queued) /*&& (! sending)*/ && args != null && args.conn != null) { sendPool.Put(args); } //txList.Clear (); //txListBytes = 0; var kickArgs = kickPool.Take(this); var data = (byte[])msg.content; kickArgs.SetBuffer(data, 0, data.Length); if (!socket.SendAsync(kickArgs)) { if (!socket.DisconnectAsync(kickArgs)) { KickCompleted(kickArgs); } } return(false); } } } if (escape) { flush = true; } if (txListBytes >= 1450 || (txListBytes > 0 && flush)) { if (args == null) { args = sendPool.Take(this); } if (txList.Count > 1) { args.SetBuffer(null, 0, 0); args.BufferList = txList; } else { var seg = txList[0]; args.BufferList = null; args.SetBuffer(seg.Array, seg.Offset, seg.Count); } // var o = 0; // for (int i = 0; i < txList.Count; i++) // o += 40 * (1 + txList[i].Count / 1460) + txList[i].Count; // var n = 40 * (1 + txListBytes / 1460) + txListBytes; // Interlocked.Add (ref totalBytesBuffered, (long)n); // Interlocked.Add (ref totalBytesUnbuffered, (long)o); BytesSent += n; try { queued = socket.SendAsync(args); } finally { if (!queued) { TxListClear(); if (escape) { MessageSendCompleted(); } } } } return(queued); } catch (SocketException e) { HandleError(e.SocketErrorCode); } catch (ObjectDisposedException) { HandleError(SocketError.OperationAborted); } return(false); }