예제 #1
0
        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");
            }
        }
예제 #2
0
        //#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);
        }