/// <summary> /// 压缩文件,参数是输入文件路径和输出文件路径。 /// </summary> /// <param name="sourceFile">输入文件路径</param> /// <param name="destinationFile">输出文件路径</param> public static void CompressFile(string sourceFile, string destinationFile) { // make sure the source file is there if (File.Exists(sourceFile) == false) { throw new FileNotFoundException(); } // Create the streams and byte arrays needed byte[] buffer = null; FileStream sourceStream = null; FileStream destinationStream = null; GZipStream compressedStream = null; try { // Read the bytes from the source file into a byte array sourceStream = new FileStream(sourceFile, FileMode.Open, FileAccess.Read, FileShare.Read); // Read the source stream values into the buffer buffer = new byte[sourceStream.Length]; int checkCounter = sourceStream.Read(buffer, 0, buffer.Length); if (checkCounter != buffer.Length) { throw new ApplicationException(); } // Open the FileStream to write to destinationStream = new FileStream(destinationFile, FileMode.OpenOrCreate, FileAccess.Write); // Create a compression stream pointing to the destiantion stream compressedStream = new GZipStream(destinationStream, CompressionMode.Compress, true); // Now write the compressed data to the destination file compressedStream.Write(buffer, 0, buffer.Length); } catch (ApplicationException e) { DxDebug.LogWarning("GZip.CompressFile():异常:" + e.Message); } finally { // Make sure we allways close all streams if (sourceStream != null) { sourceStream.Close(); } if (compressedStream != null) { compressedStream.Close(); } if (destinationStream != null) { destinationStream.Close(); } } }
/// <summary> /// 压缩一段数据,这个数据长度不能过大,最好在1M以内 /// </summary> /// <param name="sourceData">用于存储压缩字节的数组</param> /// <param name="offset">数组中开始读取的位置</param> /// <param name="count">压缩的字节数</param> /// <returns></returns> public static byte[] CompressBytes(byte[] sourceData, int offset, int count) { if (sourceData == null) { return(null); } MemoryStream destinationStream = new MemoryStream(); GZipStream compressedStream = new GZipStream(destinationStream, CompressionMode.Compress); try { compressedStream.Write(sourceData, offset, count); compressedStream.Close(); byte[] CompressedData = destinationStream.ToArray(); destinationStream.Close(); return(CompressedData); } catch (Exception e) { DxDebug.LogWarning("GZip.CompressBytes():异常:" + e.Message); } finally { // Make sure we allways close all streams if (destinationStream != null) { destinationStream.Close(); } } return(null); }
private void Dispose(bool disposing) { if (disposed) { return; } if (disposing) { // 清理托管资源 } // 清理非托管资源 try { if (_timer != null) { _timer.Dispose(); } } catch (Exception e) { DxDebug.LogWarning("ServerTimer.Dispose():异常_timer.Dispose()" + e.Message); } //让类型知道自己已经被释放 disposed = true; }
/// <summary> /// 定时器函数 /// </summary> /// <param name="state"></param> private void OnTimerTick(object state) { try { //如果自动心跳包功能打开了 if (Config.IsAutoHeartbeat == true) { CheckOffLineAndSend(); } //执行事件 if (EventOnTimer != null) { try { EventOnTimer(); } catch (Exception e) { DxDebug.LogWarning("ServerTimer.OnTimerTick():执行EventOnTimer事件异常:" + e.Message);; } } } catch (Exception e) { DxDebug.LogWarning("ServerTimer.OnTimerTick():异常:" + e.Message); } }
/// <summary> /// 添加一个token /// </summary> /// <param name="token"></param> internal Token AddToken(Token token) { lock (this._lockDict) { token.ID = _curID; _dictToken.Add(token.ID, token); //递增ID计数,额,不过上面已经加锁了 Interlocked.Increment(ref _curID); _isDictEqualArr = false; //标记当前字典和列表已经不一致了 } if (EventAddToken != null) //事件 { try { EventAddToken(token.ID); } catch (Exception e) { DxDebug.LogWarning("TokenManager.AddToken():执行事件EventAddToken异常!" + e.Message); } } DxDebug.LogConsole(String.Format("TokenManager.AddToken():添加了一个客户端. 当前服务器上有{0}个客户端; ip:{1}", _dictToken.Count, token.IP)); return(token); }
/// <summary> /// 开始接受客户端的Accept /// </summary> private void StartAccept(SocketAsyncEventArgs eArg) { //lock (_lockAccept)//这个加锁没有解决问题 //{ try { if (eArg == null) { eArg = new SocketAsyncEventArgs(); eArg.Completed += new EventHandler <SocketAsyncEventArgs>(OnIOCompleted); } eArg.AcceptSocket = null; // 必须要先清掉Socket DxDebug.LogConsole("SocketListener.StartAccept():服务器开始接收认证!"); //开始异步接收认证 if (!_listenSocket.AcceptAsync(eArg)) { this.ProcessAccept(eArg); } } catch (Exception e) { DxDebug.LogWarning("SocketListener.StartAccept():异常:" + e.Message); // throw; } //} }
/// <summary> /// 添加一个工作任务到消息队列,提供给这些线程来处理 /// </summary> /// <param name="msg"></param> public void AddMessage(IWorkMsg msg) { try { if (_msgQueue.EnqueueMaxLimit(msg)) { if (_curSemCount < 1)//如果当前的信号量剩余不多的时候 { Interlocked.Increment(ref _curSemCount); _msgSemaphore.Release();// 释放信号量 } } else { DxDebug.LogWarning("WorkThread.AddMessage():大于工作线程的能力了,丢弃了一条消息!"); } if (_msgQueuePeakLength < _msgQueue.Count) { _msgQueuePeakLength = _msgQueue.Count;//记录当前的峰值长度 } } catch (SemaphoreFullException) { DxDebug.LogError("WorkThread.AddMessage():大于工作线程的能力了:"); throw; } catch (Exception e) { DxDebug.LogError("WorkThread.AddMessage():异常:" + e.Message); throw; } }
/// <summary> /// 开始一个接收 /// </summary> private void PrepareReceive() { try { //这里是需要的,否则在断线之后仍然可能不停的接收 if (!_clientSocket.Connected) //如果当前没有连接上,就不接收了 { return; } #if !NEW_EVENT_AEGS _receiveArgs.SetBuffer(_receiveBuffer, 0, _receiveBuffer.Length); #else SocketAsyncEventArgs receiveArgs = new SocketAsyncEventArgs(); receiveArgs.UserToken = this.clientSocket; receiveArgs.RemoteEndPoint = this.hostEndPoint; byte[] receiveBuffer = new byte[2048]; //接收buffer大小为2048; receiveArgs.SetBuffer(receiveBuffer, 0, receiveBuffer.Length); receiveArgs.Completed += new EventHandler <SocketAsyncEventArgs>(OnReceive); #endif if (!_clientSocket.ReceiveAsync(_receiveArgs))//开始接收 { ProcessReceive(this, _receiveArgs); } _receTime.WaitStart(); } catch (Exception e) { DxDebug.LogWarning("SocketClient.PrepareReceive() 开始异步接收错误:" + e.Message); //这里捕获过的异常有: // Thread creation failed. } }
/// <summary> /// 删除一个token,会自动关闭连接。会产生事件 /// </summary> /// <param name="id">根据ID删除已个Token</param> public void DeleteToken(int id) { CloseToken(id, TokenErrorType.UserDelete);//先关闭 lock (this._lockDict) { if (_dictToken.ContainsKey(id)) { _dictToken.Remove(id); _isDictEqualArr = false;//标记当前字典和数组已经不一致了 } else { return; } } if (EventDeleteToken != null)//事件 { try { EventDeleteToken(id, TokenErrorType.UserDelete);//这个是外部的调用删除 } catch (Exception e) { DxDebug.LogWarning("TokenManager.DeleteToken():执行事件EventDeleteToken异常!" + e.Message); } } DxDebug.LogConsole(String.Format("TokenManager.DeleteToken():关闭了一个客户端. 还有{0}个客户端,原因{1}", _dictToken.Count, TokenErrorType.UserDelete.ToString())); }
/// <summary> /// 发生错误后就关闭连接 /// </summary> /// <param name="e"></param> private void ProcessError(SocketAsyncEventArgs e) { DxDebug.LogWarning("SocketClient.ProcessError():进入了ProcessError. ErroType:" + e.SocketError); //显示下接收的信息 Socket s = e.UserToken as Socket; //使用传递的Token if (s.Connected) { try { DxDebug.LogConsole("SocketClient.ProcessError():调用Shutdown()关闭连接"); s.Shutdown(SocketShutdown.Both); } catch (Exception ex) { DxDebug.LogWarning("SocketClient.ProcessError() :Shutdown()异常 " + ex.Message); } finally { if (s.Connected) { s.Close(); DxDebug.LogWarning("SocketClient.ProcessError() :调用Close()关闭了连接");//这里是否必须要关闭待定 } } } //产生错误事件,这是一个很重要的事件,处理服务器连接断开等 if (EventError != null) { EventError(); } }
private void DoStart(NetWorkMsg msg) { try { DxDebug.LogConsole("DNServer.DoStart():工作线程开始执行DoStart()..."); if (_socketListener != null) { DxDebug.Log(" DNServer.DoStart():_socketListener.Dispose();"); _socketListener.Dispose(); } DxDebug.Log("DNServer.DoStart():_socketListener = new SocketListener(CONNECTIONS_BUFFER_SIZE);"); _socketListener = new SocketListener(this, CONNECTIONS_BUFFER_SIZE); DxDebug.Log("DNServer.DoStart():_socketListener.EventAccept += OnAccept;"); _socketListener.EventAccept += OnAccept; _socketListener.EventReceive += OnReceive; _socketListener.EventSend += OnSend; _socketListener.EventError += OnTokenError; DxDebug.Log("DNServer.DoStart(): _socketListener.Start(" + _port + ");"); _socketListener.Start(msg.text1, _port); DxDebug.LogConsole("DNServer.DoStart()执行完毕!"); } catch (Exception e) { DxDebug.LogWarning("DNServer.DoStart():异常 " + e.Message); } }
private void ProcessConnect(object sender, SocketAsyncEventArgs e) { try { //这种回调是新开了一个线程执行的 _areConnectDone.Set(); if (IsConnected) { PrepareReceive(); //自动开始一个接收 } else { DxDebug.LogWarning("SocketClient.ProcessConnect():没能自动开始接收 IsConnected = " + IsConnected); } if (EventConnect != null) //执行事件 { EventConnect(); } } catch (Exception ex) { DxDebug.LogWarning("SocketClient.ProcessConnect():异常:" + ex.Message); } }
private void DoReceive() { try { //不再做心跳包处理,直接发出事件 LastMsgReceTickTime = DateTime.Now.Ticks; //接收数据事件 if (EventReceData != null) { try { EventReceData(this);//发出事件:接收到了数据 } catch (Exception e) { DxDebug.LogWarning("DNClient.DoReceive():执行外部事件EventReceData 异常: " + e.Message); } } //DxDebug.Log("-----------数据解包完成,数据条数: " + findPacketResult.data.Length); } catch (Exception e) { DxDebug.LogWarning("DNClient.DoReceive():异常: " + e.Message); } }
/// <summary> /// 线程函数,向所有Token发送他们的待发送数据 /// </summary> /// <param name="msg"></param> private void DoSendAll(NetWorkMsg msg) { try { Token[] tokens = TokenManager.GetInstance().GetAllToken(); if (tokens == null) { return; } for (int i = 0; i < tokens.Length; i++) { Token token = tokens[i]; //DxDebug.Log("DoSend : ID号 " + token.ID + " 当前的SendingCount " + token.SendingCount); if (token.SendingCount < MAX_TOKEN_SENDING_COUNT) { int msgCount = token.SendQueueCount; byte[] data = token.PackSendData(_packet); //打包发送 if (data != null) { Interlocked.Add(ref Status.CountSend, msgCount); //状态统计发送递增 Interlocked.Add(ref Status.CountSendBytes, data.Length); //状态统计递增发送数据长度 _socketListener.Send(token, data); } } else //如果当前正在发送,那么这次发送完成之后,会自动的开始下一次发送:OnSend()函数 { } } } catch (Exception e) { DxDebug.LogWarning("DNServer.DoSendAll():异常 " + e.Message); } }
/// <summary> /// 发送一条数据 /// </summary> /// <param name="data">要发送的整个数据</param> public void Send(byte[] data) { if (data == null) { DxDebug.LogWarning("DNClient.Send():要发送的数据为null!"); } try { _packet2.AddSend(data, 0, data.Length);//添加这条消息到打包器 NetWorkMsg msg = _msgPool.Dequeue(); if (msg == null) { msg = new NetWorkMsg(NetWorkMsg.Tpye.C_Send); } else { msg.Reset(NetWorkMsg.Tpye.C_Send); } AddMessage(msg); } catch (Exception e) { DxDebug.LogWarning("DNClient.Send():异常 " + e.Message); } }
/// <summary> /// 发送一条数据,有起始和长度控制 /// </summary> /// <param name="data">要发送的数据</param> /// <param name="offset">数据的起始位置</param> /// <param name="count">数据的长度</param> public void Send(byte[] data, int offset, int count) { if (data == null) { DxDebug.LogWarning("DNClient.Send(data,offset,count):要发送的数据为null!"); } try { _packet2.AddSend(data, offset, count);//添加这条消息到打包器 //进行数据的预打包,然后不拷贝 NetWorkMsg msg = _msgPool.Dequeue(); if (msg == null) { msg = new NetWorkMsg(NetWorkMsg.Tpye.C_Send); } else { msg.Reset(NetWorkMsg.Tpye.C_Send); } AddMessage(msg); } catch (Exception e) { DxDebug.LogWarning("DNClient.Send(p1,p2,p3):异常 " + e.Message); } }
/// <summary> /// 由Socket开始一个异步发送 /// </summary> /// <param name="token"></param> /// <param name="data"></param> internal void Send(Token token, byte[] data) { int errorCount = 0; try { if (token.disposed == false) //如果这个token已经被释放,那就不要再发送了 { token.IncrementSendingCount(); //计数递增:这里需要及早标记,否则多线程调用SocketAsyncEventArgs会异常。 SocketAsyncEventArgs sendEventArgs = token.SendArgs; sendEventArgs.SetBuffer(data, 0, data.Length); //这里这个有可能会出现异常:"现在已经正在使用此 SocketAsyncEventArgs 实例进行异步套接字操作。 //所以这句可能要加锁 if (!token.socket.SendAsync(sendEventArgs)) //开始发送 ,这里作异常处理() { OnCompletedProcessSend(this, sendEventArgs); } } } catch (Exception e) { errorCount++; DxDebug.LogWarning("SocketListener.Send():异常:" + e.Message); token.DecrementSendingCount();//直接异常了就去掉这个计数递减 if (errorCount <= 2) { DxDebug.LogConsole("SocketListener.Send()尝试自动重试!errorCount=" + errorCount); Send(token, data); } } }
/// <summary> /// 这个函数只绑定了acceptEventArg /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void OnIOCompleted(object sender, SocketAsyncEventArgs e) { //lock (_lockAccept) //{ switch (e.LastOperation) { case SocketAsyncOperation.Accept: //当关闭Socket的时候,如果没有注销事件,那么也会进入这里,所以作了一个判断(同时注销事件也完善了) if (e.SocketError != SocketError.OperationAborted) { this.ProcessAccept(e); } break; /* case SocketAsyncOperation.Receive: * this.ProcessReceive(this,e); * break; * * case SocketAsyncOperation.Send: * this.ProcessSend(this,e); * break;*/ default: DxDebug.LogWarning("SocketListener:OnIOCompleted(): 进入了未预料的switch分支!"); break; } //} }
private void DoClose() { try { IsInited = false; DxDebug.LogConsole("DNClient.DoClose():开始释放资源 "); _disposed = true; // 清理托管资源 _msgQueue.Clear(); _msgPool.Clear(); _msgQueue = null; _msgPool = null; // 清理非托管资源 _msgSemaphore.Close(); _msgSemaphore = null; Interlocked.Exchange(ref _curSemCount, 0); if (_socketClient != null) { _socketClient.Dispose(); _socketClient = null; } IsConnecting = false; } catch (Exception e) { DxDebug.LogWarning("DNClient.DoClose():异常: " + e.Message); } }
private void ProcessReceive(object sender, SocketAsyncEventArgs e) { _receTime.WorkStart(); try { //_areReceiveDone.Set();//设置信号量(但是目前压根没用到) if (e.SocketError != SocketError.Success) { this.ProcessError(e); } if (e.BytesTransferred > 0) //有可能会出现接收到的数据长度为0的情形,如当服务器关闭连接的时候 { //写入当前接收的数据 int msgCount = _packet2.AddRece(e.Buffer, e.Offset, e.BytesTransferred); //如果确实收到了一条消息 if (msgCount > 0 && EventReceive != null) //执行事件 { EventReceive(); } } else { this.ProcessError(e); } PrepareReceive(); //开始下一个接收 } catch (Exception ex) { DxDebug.LogWarning("SocketClient:ProcessReceive():" + ex.Message); } }
private void DoWork() { DxDebug.LogConsole("DNServer.DoWork():服务器线程启动!"); while (true) { _msgSemaphore.WaitOne(); Interlocked.Decrement(ref _curSemCount); while (true) { _cpuTime.WorkStart(); //时间分析计时 #if Multitask NetWorkMsg msg1 = _msgQueue.Dequeue(); NetWorkMsg msg2 = _msgQueue.Dequeue(); if (msg1 == null && msg2 == null) { break; } else if (msg1 != null && msg2 != null)//取到了两条消息 { //再消耗一条信号量 //_msgSemaphore.WaitOne(); Interlocked.Decrement(ref _curSemCount); Parallel.Invoke(delegate() { ProcessMsg(msg1); }, delegate() { ProcessMsg(msg2); }); } else if (msg1 != null && msg2 == null) { //只有一条消息,就直接执行 ProcessMsg(msg1); } else if (msg1 == null && msg2 != null) { //只有一条消息,就直接执行 ProcessMsg(msg2); } #else NetWorkMsg msg = _msgQueue.Dequeue(); if (msg == null) //直到消息取尽之前都不停的处理 { break; } float waitTime = (DateTime.Now.Ticks - msg.timeTickCreat) / 10000;//毫秒 if (waitTime > _warringWaitTime) { _warringWaitTime += 500; DxDebug.LogWarning("DNServer.DoWork():NetWorkMsg等待处理时间过长!waitTime:" + waitTime); } else if ((_warringWaitTime - waitTime) > 500) { _warringWaitTime -= 500; } ProcessMsg(msg); #endif _cpuTime.WaitStart(); //时间分析计时 } } }
/// <summary> /// 构造函数 /// </summary> public TokenManager() { if (_instance != null) { DxDebug.LogWarning("TokenManager是个单例,被多次调用构造函数"); //this.Dispose(); //_instance = null; } }
/// <summary> /// 定时器函数 /// </summary> /// <param name="state"></param> private void OnTimerTick(object state) { DNClient client = DNClient.GetInstance(); if (Config.IsAutoHeartbeat && client.IsConnected) { float time = (DateTime.Now.Ticks - client.LastMsgSendTickTime) / 10000; if (time > Config.HeartBeatSendTime)//如果时间已经超过了那么就发送心跳包 { //发送一次心跳包 SendHeartBeat(); } } if (Config.IsAutoHeartbeat && client.IsConnected) { //如果15s没有收到心跳包 float time = (DateTime.Now.Ticks - client.LastMsgReceTickTime) / 10000; if (time > Config.HeartBeatCheckTime) { DxDebug.LogWarning("ClientTimer.OnTimerTick():长时间没有收到心跳包,判断可能已经掉线!"); client.Disconnect();//关闭连接 } } //执行事件 if (EventOnTimer != null) { try { EventOnTimer(); } catch (Exception e) { DxDebug.LogWarning("ClientTimer.OnTimerTick():执行EventOnTimer事件异常:" + e.Message); } } //执行3秒事件 if (EventOnTimer3S != null) { _count3S += KICK_TIME; if (_count3S >= 3 * 1000) //20秒 { _count3S = 0; try { EventOnTimer3S(); } catch (Exception e) { DxDebug.LogWarning("ClientTimer.OnTimerTick():执行EventOnTimer3S事件异常:" + e.Message);; } } } }
/// <summary> /// 解包当前已经接收到的原始数据,结果存放进了已接收消息队列, 返回true如果接收到了消息. /// </summary> /// <param name="packeter"> 打包方法. </param> /// <param name="length"> [out] 接收到数据长度. </param> /// /// <returns> 解包出来的消息条数(注意不是长度). </returns> internal int UnpackReceiveData(IPacket packeter, out int length) { lock (this._lockReserveData) { //拼接所有的已接受数据 byte[] alldata = _reserveQueuePacked.GetDataOnce(_reserveData); _reserveData = null;//清空已经无用的_reserveData if (alldata == null) { length = 0; //长度为0 //这个情形在客户端狂发速度过快的时候容易出现,但是不影响接收,所以去掉这个日志 //DxDebug.LogWarning("Token.UnpackReceiveData(): alldata为null!"); return(0); } length = alldata.Length; //传出这个数据长度 FindPacketResult findPacketResult = packeter.FindPacket(alldata, 0); //解包 _reserveData = findPacketResult.reserveData; //更新reserveData if (findPacketResult.dataArr != null) //将结果加入队列 { //记录下一共找到的有效消息条数 int msgCount = findPacketResult.dataArr.Length; for (int i = 0; i < findPacketResult.dataArr.Length; i++)//结果是一个消息数组 { byte[] data = findPacketResult.dataArr[i]; if (data == null) { //这里是否会频繁发生? DxDebug.LogWarning("Token.UnpackReceiveData(): 结果中的data为null!"); break; } //如果不是心跳包才加入接收消息队列 if (!Config.CompareHeartBeat(findPacketResult.dataArr[i]))//Config中的静态函数判断 { if (!_receiveQueue.EnqueueMaxLimit(findPacketResult.dataArr[i])) { DxDebug.LogWarning("Token.UnpackReceiveData():接收已解包的数据队列 丢弃了一段数据"); } } else { DxDebug.LogFileOnly("Token.UnpackReceiveData():接收到了心跳包 TokenID:" + this.ID); } } LastMsgReceTickTime = DateTime.Now.Ticks; //记录最近一次接收到消息的时间 //DxDebug.Log("某个token接收到了 " + findPacketResult.data.Length + "条消息"); return(msgCount); } else { DxDebug.LogWarning("Token.UnpackReceiveData():接收到数据,经过FindPacket(),但是没有找到有效消息!"); return(0); } } }
/// <summary> /// 添加一条要发送的消息(未打包的数据),不会自动发送。 /// 这一个方法会进行数据的预打包 /// </summary> /// <param name="data">要发送的数据</param> /// <param name="index">数据起始</param> /// <param name="length">数据长度</param> public void AddSendData(byte[] data, int index, int length) { IPacket packet = DNServer.GetInstance().Packet; //进行预打包然后加入到队列 if (!_sendQueue.EnqueueMaxLimit(packet.PrePack(data, index, length))) { DxDebug.LogWarning("Token.AddSendData():要发送的数据队列 丢弃了一段数据"); } }
private void Dispose(bool disposing) { if (_disposed) { return; } IsInited = false; try { //最先去把线程关了 if (_workThread != null && _workThread.IsAlive) { DxDebug.LogConsole("DNClient.Dispose():_workThread.Abort()线程中断!"); _workThread.Abort(); } } catch (Exception e) { DxDebug.LogWarning("DNClient.Dispose(): _workThread.Abort()异常" + e.Message); } finally { _workThread = null; } try { if (disposing) { // 清理托管资源 _msgQueue.Clear(); _msgPool.Clear(); _msgQueue = null; _msgPool = null; } // 清理非托管资源 _packet2.Clear(); _msgSemaphore.Close(); _msgSemaphore = null; if (_socketClient != null) { _socketClient.Dispose(); _socketClient = null; } } catch (Exception e) { DxDebug.LogWarning("DNClient.Dispose():释放异常" + e.Message); } //让类型知道自己已经被释放 _disposed = true; IsConnecting = false; }
/// <summary> /// 连接服务器,输入IP和端口号。会强制重新初始化整个类,这样起到底层重启的作用。 /// </summary> /// <param name="host">主机IP</param> /// <param name="port">端口号</param> public void Connect(string host, int port) { try { DxDebug.LogConsole("DNClient.Connect():连接服务器 主机:" + host + " 端口:" + port); //标记正在连接 IsConnecting = true; //if (_disposed) //{ // DxDebug.LogConsole("DNClient.Connect():这个类对象是被释放状态,重新初始化"); Init(); //} //进行一次连接的时候,把消息队列清空 Clear(); Interlocked.Exchange(ref this._host, host); //给类成员赋值 Interlocked.Exchange(ref this._port, port); //给类成员赋值 NetWorkMsg msg = _msgPool.Dequeue(); if (msg == null) { msg = new NetWorkMsg(NetWorkMsg.Tpye.C_Connect); } else { msg.Reset(NetWorkMsg.Tpye.C_Connect); } AddMessage(msg); LastMsgReceTickTime = DateTime.Now.Ticks; LastMsgSendTickTime = DateTime.Now.Ticks; } catch (Exception e) { IsConnecting = false;//连接失败了 DxDebug.LogError("DNClient.Connect():异常:" + e.Message); if (EventError != null) { try { EventError(this, EventType.ConnectError, e);//事件类型:ConnectError } catch (Exception e2) { DxDebug.LogWarning("DNClient.Connect():执行EventError事件异常:" + e2.Message); } } Dispose();//释放 } }
/// <summary> /// 启动服务器 /// </summary> /// <param name="hostName">服务器的ip</param> /// <param name="port">本机的服务器端口</param> internal void Start(string hostName, int port) { try { _isStarted = false; IPAddress address = IPAddress.Any; if (hostName == "Any") { address = IPAddress.Any; } else if (Regex.IsMatch(hostName, @"\d{1,3}[.]\d{1,3}[.]\d{1,3}[.]\d{1,3}")) { byte[] ipadr = new byte[4]; MatchCollection ms = Regex.Matches(hostName, @"\d{1,3}"); for (int i = 0; i < ms.Count; i++) { ipadr[i] = Convert.ToByte(hostName.Substring(ms[i].Index, ms[i].Length)); } address = new IPAddress(ipadr); } else { IPHostEntry host = Dns.GetHostEntry(hostName); IPAddress[] addressList = host.AddressList; address = addressList[addressList.Length - 1]; } IPEndPoint localEndPoint = new IPEndPoint(address, port); DxDebug.LogConsole("SocketListener.Start():尝试启动服务器 " + address + ":" + port); //创建一个监听Socket this._listenSocket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); this._listenSocket.ReceiveBufferSize = this._bufferSize; this._listenSocket.SendBufferSize = this._bufferSize; if (localEndPoint.AddressFamily == AddressFamily.InterNetworkV6) { this._listenSocket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, false); this._listenSocket.Bind(new IPEndPoint(IPAddress.IPv6Any, localEndPoint.Port)); } else { this._listenSocket.Bind(localEndPoint); } this._listenSocket.Listen(2); //最大挂起数 this.StartAccept2(); _isStarted = true;//服务器启动成功 } catch (Exception e) { DxDebug.LogWarning("SocketListener.Start():Start函数错误:" + e.Message); } }
/// <summary> /// 线程的工作函数 /// </summary> private void DoWork() { DxDebug.LogConsole("WorkThread.DoWork():工作线程启动!"); while (_isRun) { IWorkMsg msg = null; try { //记录线程空闲 RecThreadStatus(Thread.CurrentThread.ManagedThreadId, false); _msgSemaphore.WaitOne(); Interlocked.Decrement(ref _curSemCount); //记录线程开始工作 RecThreadStatus(Thread.CurrentThread.ManagedThreadId, true); while (true) { msg = _msgQueue.Dequeue(); if (msg != null) { //递增计数 Interlocked.Increment(ref _procMsgCount); try { //取一条消息进行执行 msg.DoWork(); } catch (Exception e) { DxDebug.LogWarning("WorkThread.DoWork():执行msg异常:" + msg.Name + "异常信息:" + e.Message); } } else { break; } } } catch (Exception e) { if (msg != null) { DxDebug.LogError("WorkThread.DoWork():异常:" + msg.Name + "异常信息:" + e.Message); } else { DxDebug.LogError("WorkThread.DoWork():异常:目前IWorkMsg为null(可能空闲),异常信息:" + e.Message); } } } }
/// <summary> /// 执行异步接收完成处理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void OnCompletedProcessReceive(object sender, SocketAsyncEventArgs e) { try { // 如果返回0说明远程端已经关闭了连接,MSDN说明如下: // 此属性提供在可接收或发送数据的异步套接字操作传输的字节数。 如果从读取操作返回零,则说明远程端已关闭了连接。 if (e.BytesTransferred > 0) { if (e.SocketError == SocketError.Success) { Token token = e.UserToken as Token; token.SetData(e); /* Socket s = token.socket; * if (s.Available == 0) * { * if (EventReceive != null)//产生接收事件,通知线程进行解包 * { * EventReceive(token); * } * e.SetBuffer(token.ReceiveBuffer, 0, token.ReceiveBuffer.Length); * }*/ Socket s = token.socket;//Available的用法不太明确,但是这里有大概率是!=0的 //if (s.Available != 0) //{ // DxDebug.LogWarning("SocketListener.OnCompletedProcessReceive():s.Available != 0"); //} e.SetBuffer(token.ReceiveBuffer, 0, token.ReceiveBuffer.Length); if (EventReceive != null)//产生接收事件,通知线程进行解包 { EventReceive(token); } PrepareReceive(s, e); //开始下一个接收 } else { this.ProcessError(e); } } else { DxDebug.LogWarning("SocketListener.OnCompletedProcessReceive():BytesTransferred函数返回了零,说明远程已经关闭了连接,关闭这个用户。"); Token token = e.UserToken as Token; TokenManager.GetInstance().DeleteToken(token.ID, TokenErrorType.BytesTransferredZero);//关闭Token // token.Close(); } } catch (Exception ex) { DxDebug.LogWarning("SocketListener.OnCompletedProcessReceive():异常:" + ex.Message); } }