/// <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 // }
/// <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); //} } } }
/// <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; } } }
/// <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); } } }
/// <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); } }
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); } } } }
/// <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); } }
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); }
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); }
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); }
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); }
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); }
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); }
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); } }
/// <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); }
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); }
/// <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 // }
/// <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); }
/// <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); } }
/// <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); } }
/// <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); }
/// <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); }
/// <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) { } } //由接收事件去释放处理 }
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); }
/// <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); }
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); }
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); } } }
/// <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); } } } }
/// <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); }
/// <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); }