protected override void OnConnectServer() { //Send handshake message block to build secure connection like SSL base.Send(new MessageBlock(MessageBlockType.Handshake, (int)HandshakeType.ClientHello)); Session.Handshake = HandshakeType.ClientHello; NetDebuger.PrintDebugMessage(Session, "SEND ClientHello"); }
/// <summary> /// 停止服务器 /// </summary> protected override void OnStop() { base.OnStop(); // 关闭心跳检查功能 lock (Sessions) { TSession[] array = Sessions.ToArray(); foreach (TSession session in array) { CloseSession(session); } Sessions.Clear(); } try { Socket.Close(); } catch (ObjectDisposedException) { //服务器套接字已经关闭 } NetDebuger.PrintDebugMessage(this.GetType().Name + " Stop, clear resource success"); }
/// <summary> /// 启动心跳检查功能 /// </summary> protected override void OnStart() { if (EnableCheckHeartBeat) { checkTimer = new Timer(new TimerCallback(CheckHeartBeatCallBack), null, HeartBeatPeriod, HeartBeatPeriod); NetDebuger.PrintDebugMessage("Start heartbeat checker, Period:" + HeartBeatPeriod + "(ms)"); } }
/// <summary> /// 通讯错误事件 /// </summary> /// <param name="session"></param> /// <param name="e"></param> internal protected virtual void ReportError(TSession session, Exception e) { if (e is SocketException) { SocketException se = e as SocketException; string msg = string.Format("SocketException Code:{0}, Native Code:{1}", se.ErrorCode, se.NativeErrorCode); NetDebuger.PrintErrorMessage(session, msg); } NetDebuger.PrintErrorMessage(session, e.ToString()); }
/// <summary> /// 检查Session是否还在活动 /// </summary> /// <param name="timeOut">超时时间(ms)</param> /// <returns>正在活动返回true,否则返回false</returns> public virtual bool IsActive(int timeOut) { NetDebuger.PrintDebugMessage(this, string.Format("TimeOut:{0}-Period:{1}", timeOut, TimeCounter.Milliseconds)); if (timeOut < TimeCounter.Milliseconds) { return(false); } return(true); }
/// <summary> /// Sessions the on received message block. /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The e.</param> private void SessionOnReceivedMessageBlock(object sender, MessageBlockArgs e) { if (e.MessageBlock.Type == MessageBlockType.HeartBeat && EnableCheckHeartBeat) { Session.TimeCounter.Reset(); //Refresh the heart Beat timer NetDebuger.PrintDebugMessage(Session, "Recv server heart Beat"); } else { OnReceivedMessageBlock(e.MessageBlock); } }
/// <summary> /// 启动服务器,监听客户端连接 /// </summary> protected override void OnStart() { socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint iep = new IPEndPoint(IPAddress.Any, Port); socket.Bind(iep); socket.Listen(100); WaitForClient(); //等待客户端连接 NetDebuger.PrintDebugMessage( string.Format("{0} is running, listen port:{1} and capacity:{2}", this.GetType().Name, Port, Capacity)); base.OnStart(); //启动心跳检查功能 }
/// <summary> /// 关闭会话,把会话从服务器中移除 /// </summary> /// <param name="session">需要关闭的Session</param> protected virtual void CloseSession(TSession session) { lock (Sessions) { if (Sessions.Contains(session)) { Sessions.Remove(session); NetDebuger.PrintDebugMessage(session, "Close"); NetDebuger.PrintDebugMessage(session, string.Format("Remove:{0}/{1}", SessionsCount, Capacity)); OnCloseSession(session); //关闭前调用 session.Close(); } } }
/// <summary> /// 异步Socket中的接收新连接回调函数 /// </summary> /// <param name="parameter"></param> private void AcceptCallback(IAsyncResult parameter) { TSession session = default(TSession); try { // 创建新连接 session = CreateSession(socket.EndAccept(parameter)); if (!Full) { lock (Sessions) { Sessions.Add(session); } // 调用客户端生成函数,检查是否为合格的客户端 if (!OnCreateSession(session)) { session.Close(); return; } // 开始注册客户端数据接收事件 session.OnReceivedData += new EventHandler <DataBlockArgs>(SessionReceivedData); // 开始接收客户端数据 WaitForData(session); NetDebuger.PrintDebugMessage(session, "Create"); NetDebuger.PrintDebugMessage(session, string.Format("Add:{0}/{1}", SessionsCount, Capacity)); } else { OnServerFull(session); NetDebuger.PrintDebugMessage(session, "Server full"); session.Close(); } } catch (ObjectDisposedException) { // 监听的Socket已经关闭 } catch (SocketException e) { HandleSocketException(session, e); CloseSession(session); // 接收数据发送错误,需要关闭该Socket } finally { WaitForClient();// 继续接收客户端连接 } }
/// <summary> /// 停止检查心跳功能 /// </summary> protected override void OnStop() { if (EnableCheckHeartBeat && checkTimer != null) { lock (checkTimer) { if (EnableCheckHeartBeat && checkTimer != null) { NetDebuger.PrintDebugMessage("Stop heartbeat checker"); checkTimer.Dispose(); checkTimer = null; } } } }
protected virtual void StartHeartBeat() { /*如果EnableCheckHeartBeat=true,会启动心跳检查,这样就不能调用基类的OnStart()函数 * 服务器设定一个心跳超时时间,客户端检查超时的时间应该与此一致。客户端程序会在该时间 * 的二分之一时间内,发送一个心跳包,服务器会返回一个心跳包,这样客户端就能够知道服务器是否能够正确的响应。 */ if (EnableCheckHeartBeat) { checkTimer = new Timer(new TimerCallback(CheckHeartBeatCallBack), null, HeartBeatPeriod / 2, HeartBeatPeriod / 2); NetDebuger.PrintDebugMessage("Start heart Beat checker, Period:" + HeartBeatPeriod + "(ms)"); Session.TimeCounter.Start(); } }
/// <summary> /// 检查心跳的回调函数 /// </summary> /// <param name="o">参数(未使用)</param> protected override void CheckHeartBeatCallBack(object o) { //If client is on line, go on send heart Beat singal if (IsConnected) { base.CheckHeartBeatCallBack(o); } if (IsConnected)//如果没有掉线,继续发送心跳信号 { MessageBlock heartBeatMB = new MessageBlock(MessageBlockType.HeartBeat); Send(heartBeatMB); NetDebuger.PrintDebugMessage(Session, "Send Heart Beat"); } }
/// <summary> /// Sessions the on received message block. /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The e.</param> private void SessionOnReceivedMessageBlock(object sender, MessageBlockArgs e) { if (EnableCheckHeartBeat) { if (e.MessageBlock.Type == MessageBlockType.HeartBeat) { TSession session = (TSession)sender; //Todo:多线程安全 session.TimeCounter.Reset(); //定时器开始新的计时 Send(session, e.MessageBlock); NetDebuger.PrintDebugMessage(session, "Heartbeat"); return; } } OnReceivedMessageBlock((TSession)sender, e.MessageBlock); }
/// <summary> /// 启动心跳检查功能 /// </summary> protected override void OnStart() { IPAddress[] hostIPAddress = Dns.GetHostAddresses(Host); if (hostIPAddress.Length == 0) { throw new NetException("Get host ddress fail"); } isConnected = false; sendQueue.Clear(); IPEndPoint iep = new IPEndPoint(hostIPAddress[0], Port); socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); Socket.BeginConnect(iep, ConnectCallBack, null); serverIP = hostIPAddress[0].ToString(); NetDebuger.PrintDebugMessage(string.Format("Connecting server:{0}:{1}...", serverIP.ToString(), port)); }
/// <summary> /// 心跳检查回调函数 /// </summary> /// <param name="para"></param> protected override void CheckHeartBeatCallBack(object para) { List <TSession> closeSessions = new List <TSession>(); lock (Sessions) { foreach (TSession session in Sessions) { if (!session.IsActive(HeartBeatPeriod)) // todo:是否需要修改到服务器方法 { closeSessions.Add(session); NetDebuger.PrintDebugMessage(session, "Heartbeat is timeout and add it to closing list"); } } } foreach (TSession session in closeSessions) { CloseSession(session); } }
/// <summary> /// Called when [received command]. /// </summary> /// <param name="session">The session.</param> /// <param name="command">The command.</param> protected virtual void OnReceivedCommand(TSession session, string command) { NetDebuger.PrintDebugMessage(session, command); }
private void HandleHandshake(TSession session, HandshakeType handshakeType, MessageBlock mb) { switch (handshakeType) { case HandshakeType.ClientHello: { MessageBlock mb1 = new MessageBlock(MessageBlockType.Handshake, (int)HandshakeType.ServerHello); base.Send(session, mb1); session.Handshake = HandshakeType.ServerHello; NetDebuger.PrintDebugMessage(session, "ClientHello"); break; } case HandshakeType.ClientKeyExchange: { session.CheckPrePhase(HandshakeType.ServerHello); session.RemotePublicKey = Encoding.Unicode.GetString(mb.Body.Buffer); NetDebuger.PrintDebugMessage(session, "Client Public Key:" + session.RemotePublicKey); MessageBlock mb2 = new MessageBlock( MessageBlockType.Handshake, (int)HandshakeType.ServerKeyExchange, new DataBlock(Encoding.Unicode.GetBytes(key.PublicKey))); base.Send(session, mb2); session.Handshake = HandshakeType.ServerKeyExchange; NetDebuger.PrintDebugMessage(session, "ClientKeyExchange"); break; } case HandshakeType.ClientSymmetricKey: { session.CheckPrePhase(HandshakeType.ServerKeyExchange); byte[] key = Singleton <RSACryptServiceBase> .Instance.Decrypt( mb.Body.Buffer, this.key.XmlString); session.SymmetricCryptService.SA.Key = key; NetDebuger.PrintDebugMessage(session, "Client SA Key:" + Convert.ToBase64String(key)); MessageBlock getKeymb = new MessageBlock(MessageBlockType.Handshake, (int)HandshakeType.ServerGetSymmetricKey); base.Send(session, getKeymb); session.Handshake = HandshakeType.ServerGetSymmetricKey; NetDebuger.PrintDebugMessage(session, "ClientSymmetrickey"); break; } case HandshakeType.ClientSymmetricIV: { session.CheckPrePhase(HandshakeType.ServerGetSymmetricKey); byte[] iv = Singleton <RSACryptServiceBase> .Instance.Decrypt( mb.Body.Buffer, this.key.XmlString); session.SymmetricCryptService.SA.IV = iv; NetDebuger.PrintDebugMessage(session, "Client SA IV:" + Convert.ToBase64String(iv)); MessageBlock getIVmb = new MessageBlock(MessageBlockType.Handshake, (int)HandshakeType.ServerGetSymmetricIV); base.Send(session, getIVmb); session.Handshake = HandshakeType.ServerGetSymmetricIV; NetDebuger.PrintDebugMessage(session, "ClientSymmetricIV"); break; } case HandshakeType.ClientFinished: { session.CheckPrePhase(HandshakeType.ServerGetSymmetricIV); MessageBlock mb3 = new MessageBlock(MessageBlockType.Handshake, (int)HandshakeType.ServerFinished); base.Send(session, mb3); session.Handshake = HandshakeType.OK; NetDebuger.PrintDebugMessage(session, "Client Handshake Finished"); OnBuildDataConnection(session); NetDebuger.PrintDebugMessage(session, "Build security community channel"); break; } } }
private void HandleHandshakeType(HandshakeType type, MessageBlock mb) { switch (type) { case HandshakeType.ServerHello: { NetDebuger.PrintDebugMessage(Session, "RECV ServerHello"); Session.CheckPrePhase(HandshakeType.ClientHello); MessageBlock mb1 = new MessageBlock(MessageBlockType.Handshake, (int)HandshakeType.ClientKeyExchange, new DataBlock(Encoding.Unicode.GetBytes(key.PublicKey))); base.Send(mb1); Session.Handshake = HandshakeType.ClientKeyExchange; NetDebuger.PrintDebugMessage(Session, "SEND ClientKeyExchange"); } break; case HandshakeType.ServerKeyExchange: { NetDebuger.PrintDebugMessage(Session, "RECV ServerKeyExchange"); Session.CheckPrePhase(HandshakeType.ClientKeyExchange); Session.RemotePublicKey = Encoding.Unicode.GetString(mb.Body.Buffer); //Get Crypt key data byte[] keyData = Singleton <RSACryptServiceBase> .Instance.Encrypt (Session.SymmetricCryptService.SA.Key, Session.RemotePublicKey); //Send Client Symmetric key MessageBlock skmb = new MessageBlock(MessageBlockType.Handshake, (int)HandshakeType.ClientSymmetricKey, new DataBlock(keyData)); base.Send(skmb); Session.Handshake = HandshakeType.ClientSymmetricKey; NetDebuger.PrintDebugMessage(Session, "SEND ClientSymmetricKey"); } break; case HandshakeType.ServerGetSymmetricKey: { NetDebuger.PrintDebugMessage(Session, "RECV ServerGetSymmetrickey"); Session.CheckPrePhase(HandshakeType.ClientSymmetricKey); //Get crypt iv data byte[] ivData = Singleton <RSACryptServiceBase> .Instance.Encrypt( Session.SymmetricCryptService.SA.IV, Session.RemotePublicKey); //Send Client Symmetric IV MessageBlock ivmb = new MessageBlock(MessageBlockType.Handshake, (int)HandshakeType.ClientSymmetricIV, new DataBlock(ivData)); base.Send(ivmb); Session.Handshake = HandshakeType.ClientSymmetricIV; NetDebuger.PrintDebugMessage(Session, "SEND ClientSymmetricIV"); } break; case HandshakeType.ServerGetSymmetricIV: { NetDebuger.PrintDebugMessage(Session, "RECV ServerGetSymmetricIV"); Session.CheckPrePhase(HandshakeType.ClientSymmetricIV); MessageBlock mb2 = new MessageBlock(MessageBlockType.Handshake, (int)HandshakeType.ClientFinished); base.Send(mb2); Session.Handshake = HandshakeType.ClientFinished; NetDebuger.PrintDebugMessage(Session, "SEND ClientFinished"); break; } case HandshakeType.ServerFinished: { Session.CheckPrePhase(HandshakeType.ClientFinished); Session.Handshake = HandshakeType.OK; NetDebuger.PrintDebugMessage(Session, "RECV ServerFinished. OK!"); isConnected = true; StartHeartBeat(); //为了继续接收新数据,需要立刻返回, //所以需要从新进程中调用OnBuildDataConnection(); buildConnThread = new Thread(OnBuildDataConnection); buildConnThread.Start(); } break; } }