Ejemplo n.º 1
0
        /// <summary>
        /// 向客户端发送数据
        /// </summary>
        /// <param name="data"></param>
        internal bool SendData(TMSKSocket s, TCPOutPacket tcpOutPacket, bool pushBack = true)
        {
            //SysConOut.WriteLine("由"+s.LocalEndPoint.ToString()+"->"+s.RemoteEndPoint.ToString());
            // SysConOut.WriteLine(string.Format("SendData CMD = {0}  SocketID = {1}", tcpOutPacket.PacketCmdID, s.Nid));
            // semaphore.WaitOne();
            if (s != null && tcpOutPacket != null)
            {
                // 广播的时候多个客户端同时使用同一个byte[],要特别注意
                UInt16 sendCmdId = tcpOutPacket.PacketCmdID;
                Array.Copy(BitConverter.GetBytes(sendCmdId), 0, tcpOutPacket.GetPacketBytes(), 4, 2);
            }

#if true //原来的直接发送,改为异步线程发送,减少锁定
            bool bRet = false;
            if (null != s)
            {
                // 只有连接状态才发送消息 ChenXiaojun
                if ((s as TMSKSocket).Connected)
                {
                    //缓冲数据包
                    if (GameManager.FlagSkipSendDataCall)
                    {
                        bRet = true;
                    }
                    else
                    {
                        bRet = Global._SendBufferManager.AddOutPacket(s, tcpOutPacket);
                    }
                }
            }
            // Console.WriteLine("SendData CMD = " + tcpOutPacket.PacketCmdID.ToString() + " SocketID = " + s.deviceID.ToString());
            //还回tcpoutpacket
            if (pushBack)
            {
                Global._TCPManager.TcpOutPacketPool.Push(tcpOutPacket);
            }
            // semaphore.Release();
            // SysConOut.WriteLine(string.Format("SendData CMD = {0}  SocketID = {1}", tcpOutPacket.PacketCmdID, s.Nid));
            return(bRet);
#else
            //将发送的指令送到异步队列
            SendCmdManager.getInstance().addSendCmdWrapper(new SendCmdWrapper()
            {
                socket       = s,
                tcpOutPacket = tcpOutPacket,
            });

            return(true);
#endif //
        }
Ejemplo n.º 2
0
 /// <summary>
 /// 移除相应套接字的缓存
 /// </summary>
 /// <param name="s"></param>
 public void Remove(TMSKSocket s)
 {
     //不出错的时候ErrorDict.Count都小于等于0
     if (ErrorDict.Count > 0)
     {
         lock (ErrorDict)
         {
             //if (ErrorDict.ContainsKey(s))
             //{
             ErrorDict.Remove(s);
             //}
         }
     }
 }
Ejemplo n.º 3
0
 /// <summary>
 /// 添加套接字的缓存
 /// </summary>
 /// <param name="s"></param>
 public void Add(TMSKSocket s, int iError)
 {
     lock (ErrorDict)
     {
         if (!ErrorDict.ContainsKey(s))
         {
             ErrorDict.Add(s, iError);
         }
         else
         {
             ErrorDict[s] = iError;
         }
     }
 }
Ejemplo n.º 4
0
 /// <summary>
 /// 添加套接字的缓存
 /// </summary>
 /// <param name="s"></param>
 public void Add(TMSKSocket s)
 {
     lock (BufferDict)
     {
         if (!BufferDict.ContainsKey(s))
         {
             SendBuffer sendBuffer = new SendBuffer();
             if (GameManager.FlagOptimizeLock)
             {
                 s._SendBuffer = sendBuffer;
             }
             BufferDict.Add(s, sendBuffer);
         }
     }
 }
Ejemplo n.º 5
0
 /// <summary>
 /// 从socket接收数据
 /// </summary>
 /// <param name="s"></param>
 /// <param name="readEventArgs"></param>
 private bool _ReceiveAsync(SocketAsyncEventArgs readEventArgs)
 {
     try
     {
         TMSKSocket s = (readEventArgs.UserToken as AsyncUserToken).CurrentSocket;
         return(s.ReceiveAsync(readEventArgs));
     }
     catch (Exception ex)
     {
         // SysConOut.WriteLine(string.Format("在SocketListener::_ReceiveAsync 中发生了异常错误"));
         LogManager.WriteLog(LogTypes.Error, string.Format("在SocketListener::_ReceiveAsync 中发生了异常错误"));
         string str = ex.Message.ToString();
         this.CloseClientSocket(readEventArgs, "_ReceiveAsync = " + str.Replace('\n', ' '));
         return(true);
     }
 }
Ejemplo n.º 6
0
        private void CloseClientSocket(SocketAsyncEventArgs e, string reason)
        {
            AsyncUserToken aut = e.UserToken as AsyncUserToken;
            TMSKSocket     s   = null;

            try
            {
                s = aut.CurrentSocket;
                string ip = "未知";
                try
                {
                    ip = string.Format("{0}", s.RemoteEndPoint);
                }
                catch (Exception)
                {
                }
                LogManager.WriteLog(LogTypes.Error, string.Format("远程连接关闭: {0}, 当前总共: {1}, 原因1:{2}, 原因2:{3}", new object[]
                {
                    ip,
                    this.ConnectedSocketsCount,
                    reason,
                    s.CloseReason
                }), null, true);
                this.CloseSocket(s, "");
            }
            finally
            {
                aut.CurrentSocket = null;
                aut.Tag           = null;
                if (e.LastOperation == SocketAsyncOperation.Send)
                {
                    e.SetBuffer(null, 0, 0);
                    if (null != s)
                    {
                        s.PushWriteSocketAsyncEventArgs(e);
                    }
                }
                else if (e.LastOperation == SocketAsyncOperation.Receive)
                {
                    if (null != s)
                    {
                        s.PushReadSocketAsyncEventArgs(e);
                    }
                }
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// 向TMSKSocket发送数据
        /// </summary>
        /// <param name="writeEventArgs"></param>
        /// <returns></returns>
        private bool _SendAsync(SocketAsyncEventArgs writeEventArgs, out bool exception)
        {
            exception = false;

            try
            {
                TMSKSocket s = (writeEventArgs.UserToken as AsyncUserToken).CurrentSocket;
                return(s.SendAsync(writeEventArgs));
            }
            catch (Exception ex) //此处有可能是对象非法等异常, 例如TMSKSocket对象已经无效
            {
                LogManager.WriteLog(LogTypes.Error, string.Format("在SocketListener::_SendAsync 中发生了异常错误:{0}", ex.Message));
                exception = true;
                //this.CloseClientSocket(writeEventArgs);
                return(true);
            }
        }
Ejemplo n.º 8
0
        public bool AddOutPacket(TMSKSocket s, TCPOutPacket tcpOutPacket)
        {
            SendBuffer sendBuffer = s._SendBuffer;
            bool       result;

            if (null == sendBuffer)
            {
                result = false;
            }
            else
            {
                int  canNotSendReason = -1;
                bool bRet             = sendBuffer.CanSend2(s, tcpOutPacket, ref canNotSendReason);
                if (!bRet)
                {
                    if (sendBuffer.CanLog(canNotSendReason))
                    {
                        string failedReason = FullBufferManager.GetErrorStr(canNotSendReason);
                        LogManager.WriteLog(LogTypes.Error, string.Format("向客户端{0}发送数据失败, 发送指令:{1}, 大小:{2}, 失败原因:{3}", new object[]
                        {
                            Global.GetSocketRemoteEndPoint(s, false),
                            (TCPGameServerCmds)tcpOutPacket.PacketCmdID,
                            tcpOutPacket.PacketDataSize,
                            failedReason
                        }), null, true);
                    }
                    Global._FullBufferManager.Add(s, canNotSendReason);
                    result = (canNotSendReason == 0);
                }
                else
                {
                    if (tcpOutPacket.PacketDataSize > this.MaxOutPacketSize)
                    {
                        this.MaxOutPacketSize      = tcpOutPacket.PacketDataSize;
                        this.MaxOutPacketSizeCmdID = (int)tcpOutPacket.PacketCmdID;
                    }
                    if (!bRet)
                    {
                        LogManager.WriteLog(LogTypes.Error, string.Format("向客户端{0}发送数据时加入缓存失败, 缓存空间不足, 发送指令:{1}, 大小:{2}", Global.GetSocketRemoteEndPoint(s, false), (TCPGameServerCmds)tcpOutPacket.PacketCmdID, tcpOutPacket.PacketDataSize), null, true);
                    }
                    result = bRet;
                }
            }
            return(result);
        }
Ejemplo n.º 9
0
        private bool _ReceiveAsync(SocketAsyncEventArgs readEventArgs)
        {
            bool result;

            try
            {
                TMSKSocket s = (readEventArgs.UserToken as AsyncUserToken).CurrentSocket;
                result = s.ReceiveAsync(readEventArgs);
            }
            catch (Exception ex)
            {
                LogManager.WriteLog(LogTypes.Error, string.Format("在SocketListener::_ReceiveAsync 中发生了异常错误", new object[0]), null, true);
                string str = ex.Message.ToString();
                this.CloseClientSocket(readEventArgs, str.Replace('\n', ' '));
                result = true;
            }
            return(result);
        }
Ejemplo n.º 10
0
        public void Remove(TMSKSocket s)
        {
            SendBuffer sendBuffer = null;

            lock (this.BufferDict)
            {
                if (this.BufferDict.TryGetValue(s, out sendBuffer))
                {
                    this.BufferDict.Remove(s);
                    s._SendBuffer = null;
                }
            }
            if (null != sendBuffer)
            {
                Global._MemoryManager.Push(sendBuffer.MyMemoryBlock);
            }
            Global._FullBufferManager.Remove(s);
        }
Ejemplo n.º 11
0
        private bool _SendAsync(SocketAsyncEventArgs writeEventArgs, out bool exception)
        {
            exception = false;
            bool result;

            try
            {
                TMSKSocket s = (writeEventArgs.UserToken as AsyncUserToken).CurrentSocket;
                result = s.SendAsync(writeEventArgs);
            }
            catch (Exception ex)
            {
                LogManager.WriteLog(LogTypes.Error, string.Format("在SocketListener::_SendAsync 中发生了异常错误:{0}", ex.Message), null, true);
                exception = true;
                result    = true;
            }
            return(result);
        }
Ejemplo n.º 12
0
        private bool TrySend(TMSKSocket s, bool force = false)
        {
            long ticks = TimeUtil.NOW();
            bool result;

            if (!this._IsSendding && this._CurrentBufferSize > 0 && (force || ticks - this.AddFirstPacketTicks >= SendBuffer._SendDataIntervalTicks))
            {
                this._IsSendding = true;
                Interlocked.Exchange(ref this._SendTimeoutTickCount, ticks + SendBuffer._SendDataTimeOutTicks);
                Global._TCPManager.MySocketListener.SendData(s, this._Buffer, 0, this._CurrentBufferSize, this._MemoryBlock);
                this.Reset(false);
                result = true;
            }
            else
            {
                result = false;
            }
            return(result);
        }
Ejemplo n.º 13
0
        public bool ExternalTrySend(TMSKSocket s, bool force = false, int milliseconds = 0)
        {
            long ticks = TimeUtil.NOW();

            if (ticks - this.AddFirstPacketTicks >= SendBuffer._SendDataIntervalTicks || ticks < this.AddFirstPacketTicks)
            {
                if (Monitor.TryEnter(this.SendLock))
                {
                    try
                    {
                        return(this.TrySend2(s, ticks, force));
                    }
                    finally
                    {
                        Monitor.Exit(this.SendLock);
                    }
                }
            }
            return(false);
        }
Ejemplo n.º 14
0
        private void ProcessSend(SocketAsyncEventArgs e)
        {
            if (null != this.SocketSended)
            {
                this.SocketSended(this, e);
            }
            if (e.SocketError == SocketError.Success)
            {
                Interlocked.Add(ref this.totalBytesWrite, (long)e.BytesTransferred);
            }
            e.SetBuffer(null, 0, 0);
            TMSKSocket s = (e.UserToken as AsyncUserToken).CurrentSocket;

            (e.UserToken as AsyncUserToken).CurrentSocket = null;
            (e.UserToken as AsyncUserToken).Tag           = null;
            if (null != s)
            {
                s.PushWriteSocketAsyncEventArgs(e);
            }
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Starts the server such that it is listening for incoming connection requests.
        /// </summary>
        /// <param name="localEndPoint">The endpoint which the server will listening for connection requests on.</param>
        internal void Start(string ip, int port)
        {
            if ("" == ip)
            {
                ip = "0.0.0.0";           //防止IP无效
            }
            // Get endpoint for the listener.
            IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse(ip), port);

            // Create the socket which listens for incoming connections.
            this.listenSocket = new TMSKSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            // Associate the socket with the local endpoint.
            this.listenSocket.Bind(localEndPoint);

            // Start the server with a listen backlog of 100 connections.
            this.listenSocket.Listen(100);

            // Post accepts on the listening socket.
            this.StartAccept(null);
        }
Ejemplo n.º 16
0
        public bool SendData(TMSKSocket s, byte[] buffer, int offset, int count, MemoryBlock item, SendBuffer sendBuffer)
        {
            this.GTotalSendCount++;
            SocketAsyncEventArgs writeEventArgs = s.PopWriteSocketAsyncEventArgs();

            if (null == writeEventArgs)
            {
                writeEventArgs            = new SocketAsyncEventArgs();
                writeEventArgs.Completed += this.OnIOCompleted;
                writeEventArgs.UserToken  = new AsyncUserToken
                {
                    CurrentSocket = null,
                    Tag           = null
                };
            }
            writeEventArgs.SetBuffer(buffer, offset, count);
            AsyncUserToken userToken = writeEventArgs.UserToken as AsyncUserToken;

            userToken.CurrentSocket = s;
            userToken.Tag           = item;
            userToken._SendBuffer   = sendBuffer;
            bool exception = false;

            if (!this._SendAsync(writeEventArgs, out exception))
            {
                this.ProcessSend(writeEventArgs);
            }
            if (exception)
            {
                if (null != this.SocketSended)
                {
                    this.SocketSended(this, writeEventArgs);
                }
                writeEventArgs.SetBuffer(null, 0, 0);
                userToken.CurrentSocket = null;
                userToken.Tag           = null;
                s.PushWriteSocketAsyncEventArgs(writeEventArgs);
            }
            return(!exception);
        }
Ejemplo n.º 17
0
        /// <summary>
        /// 向客户端发送数据
        /// </summary>
        /// <param name="data"></param>
        internal bool SendData(TMSKSocket s, TCPOutPacket tcpOutPacket, bool pushBack = true)
        {
#if true //原来的直接发送,改为异步线程发送,减少锁定
            bool bRet = false;
            if (null != s)
            {
                // 只有连接状态才发送消息 ChenXiaojun
                if ((s as TMSKSocket).Connected)
                {
                    //缓冲数据包
                    if (GameManager.FlagSkipSendDataCall && GameManager.CanSkipCmd(s))
                    {
                        bRet = true;
                    }
                    else
                    {
                        bRet = Global._SendBufferManager.AddOutPacket(s, tcpOutPacket);
                    }
                }
            }

            //还回tcpoutpacket
            if (pushBack)
            {
                Global._TCPManager.TcpOutPacketPool.Push(tcpOutPacket);
            }

            return(bRet);
#else
            //将发送的指令送到异步队列
            SendCmdManager.getInstance().addSendCmdWrapper(new SendCmdWrapper()
            {
                socket       = s,
                tcpOutPacket = tcpOutPacket,
            });

            return(true);
#endif //
        }
Ejemplo n.º 18
0
        /// <summary>
        /// 尝试发送数据,到最小间隔时间或者外部强迫发送才发送
        /// </summary>
        /// <param name="s"></param>
        /// <param name="force"></param>
        /// <returns></returns>
        public bool ExternalTrySend(TMSKSocket s, bool force = false, int milliseconds = 0)
        {
            if (GameManager.FlagOptimizeThreadPool4)
            {
                long ticks = TimeUtil.NOW();
                if (ticks - AddFirstPacketTicks >= _SendDataIntervalTicks)
                {
                    if (Monitor.TryEnter(SendLock))
                    {
                        try
                        {
                            return(TrySend2(s, ticks, force));
                        }
                        finally
                        {
                            Monitor.Exit(SendLock);
                        }
                    }
                }
            }
            else
            {
                if (Monitor.TryEnter(BufferLock, milliseconds))
                {
                    try
                    {
                        return(TrySend(s, force));
                    }
                    finally
                    {
                        // Ensure that the lock is released.
                        Monitor.Exit(BufferLock);
                    }
                }
            }

            return(false);
        }
Ejemplo n.º 19
0
        /// <summary>
        /// This method is invoked when an asynchronous send operation completes.
        /// The method issues another receive on the socket to read any additional
        /// data sent from the client.
        /// </summary>
        /// <param name="e">SocketAsyncEventArg associated with the completed send operation.</param>
        private void ProcessSend(SocketAsyncEventArgs e)
        {
            /// 发送数据通知函数
            if (null != SocketSended)
            {
                SocketSended(this, e);
            }

            if (e.SocketError == SocketError.Success)
            {
                Interlocked.Add(ref this.totalBytesWrite, e.BytesTransferred);
            }
            else
            {
                //this.CloseClientSocket(e);
            }

            //什么事情都不做, 收回使用的e和buffer
            // Free the SocketAsyncEventArg so they can be reused by another client.
            e.SetBuffer(null, 0, 0); //回收内存
            TMSKSocket s = (e.UserToken as AsyncUserToken).CurrentSocket;

            (e.UserToken as AsyncUserToken).CurrentSocket = null; //释放
            (e.UserToken as AsyncUserToken).Tag           = null; //释放
            if (GameManager.FlagOptimizeThreadPool3)
            {
                if (null != s)
                {
                    s.PushWriteSocketAsyncEventArgs(e);
                }
            }
            else
            {
                this.writePool.Push(e);
            }
        }
Ejemplo n.º 20
0
        /// <summary>
        /// 尝试发送所有的数据包
        /// </summary>
        public void TrySendAll()
        {
            //最大睡眠时间 毫秒
            //int maxSleepMiniSecs = 1;
            //int  sleepMiniSecs = 0;
            List <TMSKSocket> lsSocket   = new List <TMSKSocket>(2000);
            SendBuffer        sendBuffer = null;
            bool bFind = false;

            while (!_Exit)
            {
                lsSocket.Clear();

                //System.Diagnostics.Debug.WriteLine("SendBufferManager BufferDict.Count == " + BufferDict.Count);
                //遍历需要加锁吗?当这儿拿到一个buffer,Remove同时被触发,这儿的buffer仍然是有效的,最多产生异常
                //long preTicks = TimeUtil.NOW();

                //保证锁住BufferDict的时间很小
                lock (BufferDict)
                {
                    lsSocket.AddRange(BufferDict.Keys);
                }

                int lsSocketCount = lsSocket.Count;
                //foreach (var s in lsSocket)
                for (int i = 0; i < lsSocketCount; i++)
                {
                    TMSKSocket s = lsSocket[i];
                    if (null == s)
                    {
                        continue;
                    }

                    if (GameManager.FlagOptimizeLock)
                    {
                        sendBuffer = s._SendBuffer;
                        bFind      = (sendBuffer != null);
                    }
                    else
                    {
                        lock (BufferDict)
                        {
                            bFind = BufferDict.TryGetValue(s, out sendBuffer);
                        }
                    }

                    if (bFind && null != sendBuffer)
                    {
                        sendBuffer.ExternalTrySend(s, true, 0); //尝试发送,如果锁定超时,继续处理下边的指令
                    }
                }
                //foreach (var buffer in BufferDict)
                //{
                //    buffer.Value.TrySend(buffer.Key);
                //}

                /*int usedTicks = (int)(TimeUtil.NOW() - preTicks);
                 *
                 * sleepMiniSecs = Math.Max(1, maxSleepMiniSecs - usedTicks);
                 * if (sleepMiniSecs > 0)
                 * {
                 *  Thread.Sleep(sleepMiniSecs);
                 * }*/

                Thread.Sleep(20);
            }
        }
Ejemplo n.º 21
0
        /// <summary>
        /// 判读是否可以发送数据,不能发送的原因 0表示超时, 1表示缓冲区不够, 2表示大指令数据由于缓冲区被填充过半,不再发送
        /// 拆分操作发送缓冲区和异步发送调用的锁的优化版本
        /// </summary>
        /// <param name="s"></param>
        /// <param name="tcpOutPacket"></param>
        /// <param name="canNotSendReason"></param>
        /// <returns></returns>
        public bool CanSend2(TMSKSocket s, TCPOutPacket tcpOutPacket, ref int canNotSendReason)
        {
            int  cmdID = tcpOutPacket.PacketCmdID;
            long ticks = TimeUtil.NOW();

            byte[] buffer = tcpOutPacket.GetPacketBytes();
            int    count  = tcpOutPacket.PacketDataSize;

            if (null == buffer || count > buffer.Length)
            {
                return(false);
            }
            int  needRemainSize = _MaxBufferSize - count;
            bool isLargePackge  = ((int)(TCPGameServerCmds.CMD_OTHER_ROLE) == cmdID);

            lock (BufferLock)
            {
                //判读剩下空间是否足够
                if (_CurrentBufferSize >= needRemainSize)
                {
                    canNotSendReason = FullBufferManager.Error_BufferFull;
                    return(false);
                }
                else if (0 == _CurrentBufferSize)
                {
                    _AddFirstPacketTicks = ticks;
                }

                if (GameManager.FlagOptimizeLock2)
                {
                    //判断是否超时
                    if (ticks > Interlocked.Read(ref _SendTimeoutTickCount) && CanDiscardCmd(cmdID))
                    {
                        canNotSendReason = FullBufferManager.Error_SendTimeOut;
                        return(false);
                    }
                }
                else
                {
                    //判断是否超时
                    if (IsSendTimeOut() && CanDiscardCmd(cmdID))
                    {
                        canNotSendReason = FullBufferManager.Error_SendTimeOut;
                        return(false);
                    }
                }

                //对于地图特效指令,当网络延迟较大时,可以不再发送
                //if (_CurrentBufferSize > 1024)
                //{
                //    if ((int)(TCPGameServerCmds.CMD_SPR_NEWDECO) == cmdID)
                //    {
                //        canNotSendReason = FullBufferManager.Error_DiscardBigPacket;
                //        return false;
                //    }
                //}

                //对于 CMD_OTHER_ROLE_DATA 这种大数据指令,如果缓冲区只剩下一半,则不再发送

                if (isLargePackge)
                {
                    if (_CurrentBufferSize >= MaxBufferSizeForLargePackge)
                    {
                        canNotSendReason = FullBufferManager.Error_DiscardBigPacket;
                        return(false);
                    }
                }

                //改写内容的时候,锁住
                DataHelper.CopyBytes(_Buffer, _CurrentBufferSize, buffer, 0, count);
                _CurrentBufferSize += count;
                //System.Diagnostics.Debug.WriteLine(String.Format("SendBufferManager add Size == {0}, _CurrentBufferSize = {1}", count, _CurrentBufferSize));
            }

            //尝试发送
            if (!GameManager.FlagSkipAddBuffCall || !GameManager.CanSkipCmd(s))
            {
                if (Monitor.TryEnter(SendLock))
                {
                    bool force = (_CurrentBufferSize > ConstMinSendSize);
                    try
                    {
                        //立刻尝试发送,无延迟,对于网络条件较好时,不需要等待发送
                        if (!GameManager.FlagSkipTrySendCall || !GameManager.CanSkipCmd(s))
                        {
                            TrySend2(s, ticks, force);
                        }
                    }
                    finally
                    {
                        Monitor.Exit(SendLock);
                    }
                }
            }

            return(true);
        }
Ejemplo n.º 22
0
        /// <summary>
        /// 判读是否可以发送数据,不能发送的原因 0表示超时, 1表示缓冲区不够, 2表示大指令数据由于缓冲区被填充过半,不再发送
        /// </summary>
        /// <returns></returns>
        public bool CanSend(int bytesCount, int cmdID, out int canNotSendReason, byte[] buffer, TMSKSocket s)
        {
            canNotSendReason = -1;
            long ticks = TimeUtil.NOW();

            lock (BufferLock)
            {
                if (GameManager.FlagOptimizeLock2)
                {
                    //判断是否超时
                    if (ticks > Interlocked.Read(ref _SendTimeoutTickCount) && CanDiscardCmd(cmdID))
                    {
                        canNotSendReason = FullBufferManager.Error_SendTimeOut;
                        return(false);
                    }
                }
                else
                {
                    //判断是否超时
                    if (IsSendTimeOut() && CanDiscardCmd(cmdID))
                    {
                        canNotSendReason = FullBufferManager.Error_SendTimeOut;
                        return(false);
                    }
                }

                //上次发送过数据包

                /*if (_LastSendDataTicks > 0)
                 * {
                 *  //判读剩下空间是否足够
                 *  if (_MaxBufferSize - _CurrentBufferSize <= bytesCount)
                 *  {
                 *      canNotSendReason = FullBufferManager.Error_BufferFull;
                 *      return false;
                 *  }
                 * }*/

                //对于地图特效指令,当网络延迟较大时,可以不再发送
                //if (_CurrentBufferSize > 1024)
                //{
                //    if ((int)(TCPGameServerCmds.CMD_SPR_NEWDECO) == cmdID)
                //    {
                //        canNotSendReason = FullBufferManager.Error_DiscardBigPacket;
                //        return false;
                //    }
                //}

                //对于 CMD_OTHER_ROLE_DATA 这种大数据指令,如果缓冲区只剩下一半,则不再发送

                if ((int)(TCPGameServerCmds.CMD_OTHER_ROLE) == cmdID)
                {
                    if (_CurrentBufferSize >= ((_MaxBufferSize - _CurrentBufferSize) << 2))//等价优化运算公式 if (_CurrentBufferSize >= (int)(_MaxBufferSize * 2 / 3))
                    {
                        canNotSendReason = FullBufferManager.Error_DiscardBigPacket;
                        return(false);
                    }
                }

                //加入发送缓存
                if (!GameManager.FlagSkipAddBuffCall || !GameManager.CanSkipCmd(s))
                {
                    return(AddBuffer(buffer, 0, bytesCount, s));
                }
            }

            return(true);
        }
Ejemplo n.º 23
0
        /// <summary>
        /// 关闭指定的TMSKSocket连接
        /// </summary>
        /// <param name="s"></param>
        public void CloseSocket(TMSKSocket s)
        {
            //try
            //{
            //    s.Shutdown(SocketShutdown.Both);

            //    // 需要Close 不然不会收到套接字关闭 ChenXiaojun
            //    s.Close();
            //}
            //catch (Exception ex)
            //{
            //    // Throws if client process has already closed.
            //    try
            //    {
            //        LogManager.WriteLog(LogTypes.Info, string.Format("CloseSocket 异常: {0}, {1}", s.RemoteEndPoint, ex.Message));
            //    }
            //    catch (Exception)
            //    {
            //    }
            //}

            if (!FindSocket(s)) //已经关闭了
            {
                //已经关闭之后再调用一次
                Global._SendBufferManager.Remove(s);
                return;
            }

            RemoveSocket(s);

            /// 断开成功通知函数
            if (null != SocketClosed)
            {
                SocketClosed(this, s);
            }

            //在这个位置调用,避免遗漏,重复调用不会出错
            Global._SendBufferManager.Remove(s);

            try
            {
                s.Shutdown(SocketShutdown.Both);
            }
            catch (Exception ex)
            {
                // Throws if client process has already closed.
                try
                {
                    LogManager.WriteLog(LogTypes.Info, string.Format("CloseSocket s.Shutdown()异常: {0}, {1}", s.RemoteEndPoint, ex.Message));
                }
                catch (Exception)
                {
                }
            }

            try
            {
                s.Close();
            }
            catch (Exception ex)
            {
                // Throws if client process has already closed.
                try
                {
                    LogManager.WriteLog(LogTypes.Info, string.Format("CloseSocket s.Close()异常: {0}, {1}", s.RemoteEndPoint, ex.Message));
                }
                catch (Exception)
                {
                }
            }

            //由接收事件去释放处理
        }
Ejemplo n.º 24
0
        public bool CanSend(int bytesCount, int cmdID, out int canNotSendReason, byte[] buffer, TMSKSocket s)
        {
            canNotSendReason = -1;
            long ticks = TimeUtil.NOW();
            bool result;

            lock (this.BufferLock)
            {
                if (ticks > Interlocked.Read(ref this._SendTimeoutTickCount) && this.CanDiscardCmd(cmdID))
                {
                    canNotSendReason = 0;
                    result           = false;
                }
                else
                {
                    if (110 == cmdID)
                    {
                        if (this._CurrentBufferSize >= this._MaxBufferSize - this._CurrentBufferSize << 2)
                        {
                            canNotSendReason = 2;
                            return(false);
                        }
                    }
                    result = this.AddBuffer(buffer, 0, bytesCount, s);
                }
            }
            return(result);
        }
Ejemplo n.º 25
0
        /// <summary>
        /// Process the accept for the socket listener.
        /// </summary>
        /// <param name="e">SocketAsyncEventArg associated with the completed accept operation.</param>
        private void ProcessAccept(SocketAsyncEventArgs e)
        {
            //Socket s = e.AcceptSocket;
            TMSKSocket s = new TMSKSocket(e.AcceptSocket);

            //检查IP名单
            bool disableConnect = false;

            if (EnabledIPListFilter)
            {
                lock (IPWhiteList)
                {
                    if (EnabledIPListFilter && null != s && null != s.RemoteEndPoint)
                    {
                        IPEndPoint remoteIPEndPoint = (s.RemoteEndPoint as IPEndPoint);
                        if (null != remoteIPEndPoint && null != remoteIPEndPoint.Address)
                        {
                            string remoteIP = remoteIPEndPoint.Address.ToString();
                            if (!string.IsNullOrEmpty(remoteIP) && !IPWhiteList.ContainsKey(remoteIP))
                            {
                                disableConnect = true;
                            }
                        }
                    }
                }
            }

            //是否不再接受新的用户
            if (DontAccept || disableConnect)
            {
                try
                {
                    if (disableConnect)
                    {
                        LogManager.WriteLog(LogTypes.Error, string.Format("新远程连接: {0}, 但是客户端IP处于IP过滤中,直接关闭连接:{1}", s.RemoteEndPoint, ConnectedSocketsCount));
                    }
                    else if (DontAccept)
                    {
                        LogManager.WriteLog(LogTypes.Error, string.Format("新远程连接: {0}, 但是服务器端处于不接受新连接状态,直接关闭连接:{1}", s.RemoteEndPoint, ConnectedSocketsCount));
                    }
                }
                catch (Exception)
                {
                }

                try
                {
                    s.Shutdown(SocketShutdown.Both);
                }
                catch (Exception)
                {
                    // Throws if client process has already closed.
                }

                try
                {
                    s.Close();
                }
                catch (Exception)
                {
                }

                // Accept the next connection request.
                this.StartAccept(e);
                return;
            }

            byte[] inOptionValues = new byte[sizeof(uint) * 3];
            BitConverter.GetBytes((uint)1).CopyTo(inOptionValues, 0);
            BitConverter.GetBytes((uint)120000).CopyTo(inOptionValues, sizeof(uint));
            BitConverter.GetBytes((uint)5000).CopyTo(inOptionValues, sizeof(uint) * 2);
            (s as TMSKSocket).IOControl(IOControlCode.KeepAliveValues, inOptionValues, null);

            SocketAsyncEventArgs readEventArgs = null;

            if (GameManager.FlagOptimizeThreadPool3)
            {
                readEventArgs = s.PopReadSocketAsyncEventArgs(); //线程安全的操作
            }
            else
            {
                readEventArgs = this.readPool.Pop();
            }
            if (null == readEventArgs)
            {
                try
                {
                    LogManager.WriteLog(LogTypes.Error, string.Format("新远程连接: {0}, 但是readPool内的缓存不足,直接关闭连接:{1}", s.RemoteEndPoint, ConnectedSocketsCount));
                }
                catch (Exception)
                {
                }

                try
                {
                    s.Shutdown(SocketShutdown.Both);
                }
                catch (Exception)
                {
                    // Throws if client process has already closed.
                }

                try
                {
                    s.Close();
                }
                catch (Exception)
                {
                }

                // Accept the next connection request.
                this.StartAccept(e);
                return;
            }

            //增加计数器
            //Interlocked.Increment(ref this.numConnectedSockets);

            // Get the socket for the accepted client connection and put it into the
            // ReadEventArg object user token.
            (readEventArgs.UserToken as AsyncUserToken).CurrentSocket = s;

            Global._SendBufferManager.Add(s);

            AddSocket(s);

            try
            {
                LogManager.WriteLog(LogTypes.Error, string.Format("新远程连接: {0}, 当前总共: {1}", s.RemoteEndPoint, ConnectedSocketsCount));
            }
            catch (Exception)
            {
            }

            /// 连接成功通知函数
            if (null != SocketConnected)
            {
                SocketConnected(this, readEventArgs);
            }

            // As soon as the client is connected, post a receive to the connection.
            Boolean willRaiseEvent = _ReceiveAsync(readEventArgs);

            if (!willRaiseEvent)
            {
                this.ProcessReceive(readEventArgs);
            }

            // Accept the next connection request.
            this.StartAccept(e);
        }
Ejemplo n.º 26
0
        public bool CanSend2(TMSKSocket s, TCPOutPacket tcpOutPacket, ref int canNotSendReason)
        {
            int  cmdID = (int)tcpOutPacket.PacketCmdID;
            long ticks = TimeUtil.NOW();

            byte[] buffer = tcpOutPacket.GetPacketBytes();
            int    count  = tcpOutPacket.PacketDataSize;
            bool   result;

            if (buffer == null || count > buffer.Length)
            {
                result = false;
            }
            else
            {
                TCPManager.RecordCmdOutputDataSize(cmdID, (long)count);
                int  needRemainSize = this._MaxBufferSize - count;
                bool isLargePackge  = 110 == cmdID;
                lock (this.BufferLock)
                {
                    if (this._CurrentBufferSize >= needRemainSize)
                    {
                        canNotSendReason = 1;
                        return(false);
                    }
                    if (0 == this._CurrentBufferSize)
                    {
                        this._AddFirstPacketTicks = ticks;
                    }
                    if (ticks > Interlocked.Read(ref this._SendTimeoutTickCount) && this.CanDiscardCmd(cmdID))
                    {
                        canNotSendReason = 0;
                        return(false);
                    }
                    if (isLargePackge)
                    {
                        if (this._CurrentBufferSize >= SendBuffer.MaxBufferSizeForLargePackge)
                        {
                            canNotSendReason = 2;
                            return(false);
                        }
                    }
                    DataHelper.CopyBytes(this._Buffer, this._CurrentBufferSize, buffer, 0, count);
                    this._CurrentBufferSize += count;
                }
                if (Monitor.TryEnter(this.SendLock))
                {
                    bool force = this._CurrentBufferSize > SendBuffer.ConstMinSendSize;
                    try
                    {
                        this.TrySend2(s, ticks, force);
                    }
                    finally
                    {
                        Monitor.Exit(this.SendLock);
                    }
                }
                result = true;
            }
            return(result);
        }
Ejemplo n.º 27
0
        private void ProcessAccept(SocketAsyncEventArgs e)
        {
            TMSKSocket s = new TMSKSocket(e.AcceptSocket);

            s.SetAcceptIp();
            bool disableConnect = false;
            bool?inIpWriteList  = null;

            if (this.EnabledIPListFilter)
            {
                lock (this.IPWhiteList)
                {
                    if (this.EnabledIPListFilter && s != null && null != s.RemoteEndPoint)
                    {
                        IPEndPoint remoteIPEndPoint = s.RemoteEndPoint as IPEndPoint;
                        if (remoteIPEndPoint != null && null != remoteIPEndPoint.Address)
                        {
                            string remoteIP = remoteIPEndPoint.Address.ToString();
                            if (!string.IsNullOrEmpty(remoteIP) && !this.IPWhiteList.ContainsKey(remoteIP))
                            {
                                LogManager.WriteLog(LogTypes.Error, string.Format("新远程连接: {0}, 但是客户端IP处于IP过滤中:{1}", s.RemoteEndPoint, this.ConnectedSocketsCount), null, true);
                                inIpWriteList = new bool?(false);
                            }
                            else
                            {
                                inIpWriteList = new bool?(true);
                            }
                        }
                    }
                }
            }
            if (IPStatisticsManager.getInstance().GetIPInBeOperation(s, IPOperaType.BanConnect))
            {
                disableConnect = true;
            }
            if (this.DontAccept || disableConnect)
            {
                try
                {
                    if (disableConnect)
                    {
                        LogManager.WriteLog(LogTypes.Error, string.Format("新远程连接: {0}, 但是客户端IP处于IP过滤中,直接关闭连接:{1}", s.RemoteEndPoint, this.ConnectedSocketsCount), null, true);
                    }
                    else if (this.DontAccept)
                    {
                        LogManager.WriteLog(LogTypes.Error, string.Format("新远程连接: {0}, 但是服务器端处于不接受新连接状态,直接关闭连接:{1}", s.RemoteEndPoint, this.ConnectedSocketsCount), null, true);
                    }
                }
                catch (Exception)
                {
                }
                try
                {
                    s.Shutdown(SocketShutdown.Both);
                }
                catch (Exception)
                {
                }
                try
                {
                    s.Close(30);
                }
                catch (Exception)
                {
                }
                this.StartAccept(e);
            }
            else
            {
                byte[] inOptionValues = new byte[12];
                BitConverter.GetBytes(1U).CopyTo(inOptionValues, 0);
                BitConverter.GetBytes(120000U).CopyTo(inOptionValues, 4);
                BitConverter.GetBytes(5000U).CopyTo(inOptionValues, 8);
                s.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null);
                LingerOption lingerOption = new LingerOption(true, 10);
                s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lingerOption);
                SocketAsyncEventArgs readEventArgs = null;
                readEventArgs = s.PopReadSocketAsyncEventArgs();
                if (null == readEventArgs)
                {
                    try
                    {
                        LogManager.WriteLog(LogTypes.Error, string.Format("新远程连接: {0}, 但是readPool内的缓存不足,直接关闭连接:{1}", s.RemoteEndPoint, this.ConnectedSocketsCount), null, true);
                    }
                    catch (Exception)
                    {
                    }
                    try
                    {
                        s.Shutdown(SocketShutdown.Both);
                    }
                    catch (Exception)
                    {
                    }
                    try
                    {
                        s.Close(30);
                    }
                    catch (Exception)
                    {
                    }
                    this.StartAccept(e);
                }
                else
                {
                    (readEventArgs.UserToken as AsyncUserToken).CurrentSocket = s;
                    Global._SendBufferManager.Add(s);
                    this.AddSocket(s);
                    try
                    {
                        LogManager.WriteLog(LogTypes.Error, string.Format("新远程连接: {0}, 当前总共: {1}", s.RemoteEndPoint, this.ConnectedSocketsCount), null, true);
                    }
                    catch (Exception)
                    {
                    }
                    if (null != this.SocketConnected)
                    {
                        this.SocketConnected(this, readEventArgs);
                    }
                    s.session.InIpWhiteList = inIpWriteList;
                    s.session.SetSocketTime(0);
                    if (!this._ReceiveAsync(readEventArgs))
                    {
                        this.ProcessReceive(readEventArgs);
                    }
                    this.StartAccept(e);
                }
            }
        }
Ejemplo n.º 28
0
        /// <summary>
        /// Close the socket associated with the client.
        /// </summary>
        /// <param name="e">SocketAsyncEventArg associated with the completed send/receive operation.</param>
        private void CloseClientSocket(SocketAsyncEventArgs e)
        {
            AsyncUserToken aut = e.UserToken as AsyncUserToken;

            TMSKSocket s = null;

            try
            {
                s = aut.CurrentSocket;

                string ip = "未知";

                try
                {
                    ip = string.Format("{0}", s.RemoteEndPoint);
                }
                catch (System.Exception)
                {
                }

                LogManager.WriteLog(LogTypes.Error, string.Format("远程连接关闭: {0}, 当前总共: {1}", ip, ConnectedSocketsCount));

                CloseSocket(s);
            }
            finally
            {
                aut.CurrentSocket = null; //释放
                aut.Tag           = null; //释放

                // Free the SocketAsyncEventArg so they can be reused by another client.
                if (e.LastOperation == SocketAsyncOperation.Send)
                {
                    e.SetBuffer(null, 0, 0); //回收内存
                    if (GameManager.FlagOptimizeThreadPool3)
                    {
                        //TMSKThreadStaticClass.GetInstance().PushReadSocketAsyncEventArgs(e);
                        if (null != s)
                        {
                            s.PushWriteSocketAsyncEventArgs(e);
                        }
                    }
                    else
                    {
                        this.writePool.Push(e);
                    }
                }
                else if (e.LastOperation == SocketAsyncOperation.Receive)
                {
                    if (GameManager.FlagOptimizeThreadPool3)
                    {
                        //TMSKThreadStaticClass.GetInstance().PushReadSocketAsyncEventArgs(e);
                        if (null != s)
                        {
                            s.PushReadSocketAsyncEventArgs(e);
                        }
                    }
                    else
                    {
                        this.readPool.Push(e);
                    }
                }
            }
        }
Ejemplo n.º 29
0
        /// <summary>
        /// 添加输出数据包
        /// </summary>
        /// <param name="s"></param>
        /// <param name="tcpOutPacket"></param>
        /// <returns></returns>
        public bool AddOutPacket(TMSKSocket s, TCPOutPacket tcpOutPacket)
        {
            bool bRet;
            //发出去的信息不再进行加密处理, 客户端的接受也修改为不做解密处理
            //字节排序
            //DataHelper.SortBytes(tcpOutPacket.GetPacketBytes(), 0, tcpOutPacket.PacketDataSize);

            SendBuffer sendBuffer = null;

            if (GameManager.FlagOptimizeLock)
            {
                sendBuffer = s._SendBuffer;
                if (null == sendBuffer)
                {
                    return(false);
                }
            }
            else
            {
                lock (BufferDict)
                {
                    if (!BufferDict.TryGetValue(s, out sendBuffer))
                    {
                        //sendBuffer = new SendBuffer();
                        //lock (BufferDict)
                        //{
                        //    BufferDict.Add(s, sendBuffer);
                        //}
                        //不要在这儿动态添加,外部调用这个函数的时机很复杂,可能会在连接断开之后再调用,产生死socket的缓存
                        return(false);
                    }
                }
            }

            int canNotSendReason = -1;

            if (GameManager.FlagOptimizeThreadPool4)
            {
                bRet = sendBuffer.CanSend2(s, tcpOutPacket, ref canNotSendReason);
            }
            else
            {
                bRet = sendBuffer.CanSend(tcpOutPacket.PacketDataSize, tcpOutPacket.PacketCmdID, out canNotSendReason, tcpOutPacket.GetPacketBytes(), s);
            }
            if (!bRet)
            {
                //避免大量的重复日志记录
                if (sendBuffer.CanLog(canNotSendReason))
                {
                    string failedReason = FullBufferManager.GetErrorStr(canNotSendReason);
                    LogManager.WriteLog(LogTypes.Error, string.Format("向客户端{0}发送数据失败, 发送指令:{1}, 大小:{2}, 失败原因:{3}", Global.GetSocketRemoteEndPoint(s), (TCPGameServerCmds)tcpOutPacket.PacketCmdID, tcpOutPacket.PacketDataSize, failedReason));
                }

                if (!GameManager.FlagOptimizeLockTrace)
                {
                    Global._FullBufferManager.Add(s, canNotSendReason);
                }
                return(canNotSendReason == (int)FullBufferManager.Error_SendTimeOut);  //如果等于超时就返回true, 让外边不再频繁记日志,只有丢弃的包才让外边也记日志
            }

            //加入发送缓存
            //bRet = sendBuffer.AddBuffer(tcpOutPacket.GetPacketBytes(), 0, tcpOutPacket.PacketDataSize, s);

            //记录发出的最大数据包
            if (tcpOutPacket.PacketDataSize > MaxOutPacketSize)
            {
                MaxOutPacketSize      = tcpOutPacket.PacketDataSize;
                MaxOutPacketSizeCmdID = tcpOutPacket.PacketCmdID;
            }

            //返回错误,应该是缓冲区满,立即发送
            if (!bRet)
            {
                LogManager.WriteLog(LogTypes.Error, string.Format("向客户端{0}发送数据时加入缓存失败, 缓存空间不足, 发送指令:{1}, 大小:{2}", Global.GetSocketRemoteEndPoint(s), (TCPGameServerCmds)tcpOutPacket.PacketCmdID, tcpOutPacket.PacketDataSize));

                /*
                 * //这儿不用再判断数据是否发送成功
                 * sendBuffer.TrySend(s, true);
                 * //if (sendBuffer.TrySend(s, true))
                 * //{
                 *  //发送完毕之后,再尝试添加缓冲数据
                 *  bRet = sendBuffer.AddBuffer(tcpOutPacket.GetPacketBytes(), 0, tcpOutPacket.PacketDataSize);
                 *
                 *  //如果添加失败,则直接发送----对于大数据有用
                 *  if (!bRet)
                 *  {
                 *      int nSendLen = tcpOutPacket.PacketDataSize;
                 *      //System.Diagnostics.Debug.WriteLine("SendBufferManager 某些数据包太大,直接发送 tcpOutPacket.PacketDataSize== " + tcpOutPacket.PacketDataSize);
                 *
                 *      //如果还失败,直接发送--->异步发送的时候是拷贝了内存,如果内存块是被管理的,这儿就多拷贝一次
                 *      if (!tcpOutPacket.MyMemoryBlock.isManaged)
                 *      {
                 *          //对于不受管理的内存,这儿直接发送
                 *          bRet = Global._TCPManager.MySocketListener.SendData(s, tcpOutPacket.GetPacketBytes(), 0, tcpOutPacket.PacketDataSize, null);
                 *      }
                 *      else
                 *      {
                 *          //对于受管理的内存,考虑到tcpOutPacket会还回内存池,该内存可能会被用做其他用途,导致混乱,这儿重新拷贝一份
                 *          MemoryBlock block = Global._MemoryManager.Pop(nSendLen);
                 *          DataHelper.CopyBytes(block.Buffer, 0, tcpOutPacket.GetPacketBytes(), 0, nSendLen);
                 *
                 *          bRet = Global._TCPManager.MySocketListener.SendData(s, block.Buffer, 0, nSendLen, block);
                 *      }
                 *  }
                 * //}
                 */
            }

            return(bRet);
        }
Ejemplo n.º 30
0
        /// <summary>
        /// 向客户端发送数据
        /// </summary>
        /// <param name="data"></param>
        public bool SendData(TMSKSocket s, Byte[] buffer, int offset, int count, MemoryBlock item, SendBuffer sendBuffer)
        {
            GTotalSendCount++;
            SocketAsyncEventArgs writeEventArgs;

            if (GameManager.FlagOptimizeThreadPool3)
            {
                writeEventArgs = s.PopWriteSocketAsyncEventArgs(); //线程安全的操作
            }
            else
            {
                writeEventArgs = this.writePool.Pop(); //线程安全的操作
            }
            if (null == writeEventArgs)
            {
                writeEventArgs            = new SocketAsyncEventArgs();
                writeEventArgs.Completed += new EventHandler <SocketAsyncEventArgs>(OnIOCompleted);
                writeEventArgs.UserToken  = new AsyncUserToken()
                {
                    CurrentSocket = null, Tag = null
                };
            }

            writeEventArgs.SetBuffer(buffer, offset, count);
            AsyncUserToken userToken = (writeEventArgs.UserToken as AsyncUserToken);

            userToken.CurrentSocket = s;
            userToken.Tag           = item;
            userToken._SendBuffer   = sendBuffer;

            bool exception = false;

            if (GameManager.FlagSkipSocketSend && GameManager.CanSkipCmd(s))
            {
                writeEventArgs.SocketError = SocketError.Success;
                this.ProcessSend(writeEventArgs);
            }
            else
            {
                Boolean willRaiseEvent = _SendAsync(writeEventArgs, out exception);
                if (!willRaiseEvent)
                {
                    this.ProcessSend(writeEventArgs);
                }
            }

            if (exception) //此处不处理会导致内存泄露
            {
                /// 发送数据通知函数
                if (null != SocketSended)
                {
                    SocketSended(this, writeEventArgs);
                }

                //什么事情都不做, 收回使用的e和buffer
                // Free the SocketAsyncEventArg so they can be reused by another client.
                writeEventArgs.SetBuffer(null, 0, 0); //回收内存
                userToken.CurrentSocket = null;       //释放
                userToken.Tag           = null;       //释放
                if (GameManager.FlagOptimizeThreadPool3)
                {
                    s.PushWriteSocketAsyncEventArgs(writeEventArgs);
                }
                else
                {
                    this.writePool.Push(writeEventArgs);
                }
            }

            return(!exception);
        }