/* Sog 游戏基础库 2016 by zouwei */ using System; using System.Net; using System.Net.Sockets; using System.Collections.Generic; using System.Security.Cryptography; namespace SogClient { /// /// Client socket. /// public class WebClientSession : IMessageTransWeb, IDisposable { public WebSession m_webSession { get; private set; } private ClientSessionSettings m_clientSettings; protected ConnectedClientSessionUpdate m_sessionUpdate; /// /// connected. /// public bool IsConnected { get { if (m_isConnected == false) { return false; } //如果加密需要收到key if (m_clientSettings.CryptoMessage && m_teaKey == null) { return false; } return true; } } private bool m_isConnecting = false; private bool m_isConnected; static object m_rsaCrypto; SogFastXTEAKey m_teaKey; private ushort m_sendSeq; /// /// 接收到数据事件 /// public event WebNetEventHandler DataReceived; private void OnDataReceived(WebSessionEventArgs e) { TraceLog.Trace("webClientSession recv data, remote {0} SessionID {1} length {2}", e.Session.RemoteEndPoint, e.Session.SessionID, e.Message.Header.Length); if (m_clientSettings.CryptoMessage) { if (e.Message.Header.Type == (int)SpecialMessageType.SessionKey) { OnSessionKeyReceive(e.Message); return; } } if (DataReceived != null) { DataReceived(this, e); } } /// /// 连接成功事件 /// public event WebNetEventHandler Connected; private void OnConnected(WebSessionEventArgs e) { TraceLog.Trace("WebClientSession connect {0} success", m_clientSettings.RemoteEndPoint); //如果需要加密在收到key消息后connected if (m_clientSettings.CryptoMessage) { TraceLog.Trace("WebClientSession need cryptomessage,so wait sessionkey message", m_clientSettings.RemoteEndPoint); return; } } /// /// 连接失败事件 /// public event WebNetEventHandler ConnectFail; private void OnConnectFail(WebSessionEventArgs e) { TraceLog.Trace("WebClientSession connect {0} failed", m_clientSettings.RemoteEndPoint); if (ConnectFail != null) { ConnectFail(this, e); } m_isConnected = false; m_isConnecting = false; CloseWebSocket(); } /// /// 连接断开事件 /// public event WebNetEventHandler Disconnected; private void OnDisconnected(WebSessionEventArgs e) { TraceLog.Trace("WebClientSession connection lost {0} ", m_clientSettings.RemoteEndPoint); if (Disconnected != null) { Disconnected(this, e); } m_isConnected = false; m_isConnecting = false; CloseWebSocket(); } private void CloseWebSocket() { //清空密钥,重新连接就需要重新请求密钥 m_teaKey = null; m_sendSeq = 0; TraceLog.Debug("CloseWebSocket 11111"); if (m_webSession != null) { try { m_webSession.Close(); } catch (Exception e) { TraceLog.Trace("WebClientSession CloseSocket err {0} ", e); } finally { TraceLog.Debug("CloseWebSocket 222222222222222"); m_webSession = null; } } } /// /// /// /// /// public WebClientSession(ClientSessionSettings clientSettings, ConnectedClientSessionUpdate updateMgr) { this.m_clientSettings = clientSettings; m_webSession = new WebSession(this.m_clientSettings); Console.WriteLine("WebClientSession Init"); m_sessionUpdate = updateMgr; } /// /// /// public void Reconnect() { m_isConnected = false; m_isConnecting = true; //m_socketClient = new Socket(this.m_clientSettings.RemoteEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); //m_socketClient.Blocking = false; Connect(); } /// /// Connect this instance. /// public void Connect() { TraceLog.Trace("clientsession begin connect"); m_sendSeq = 0; m_isConnected = false; try { m_isConnecting = true; m_webSession.Connect(); } catch (Exception ex) { //这个是正常的 TraceLog.Trace("connect to {0},wait connected finish SocketErrorCode err {1},", m_clientSettings.RemoteEndPoint, ex); } } public void Update() { UpdateConnect(); UpdateReadWrite(); } private void UpdateConnect() { if (m_webSession == null) { return; } if (m_isConnecting) { if (m_webSession.IsError) { WebSessionEventArgs e = new WebSessionEventArgs(); e.Session = m_webSession; OnConnectFail(e); } else if (m_webSession.IsConnected) { ConnectComplated(); } } if (m_isConnected) { if (m_webSession.IsClosed) { WebSessionEventArgs e = new WebSessionEventArgs(); e.Session = m_webSession; OnDisconnected(e); return; } else if (m_webSession.IsError) { WebSessionEventArgs e = new WebSessionEventArgs(); e.Session = m_webSession; OnDisconnected(e); return; } } } protected void UpdateReadWrite() { if (m_webSession == null) { return; } if (m_isConnected) { m_sessionUpdate.AddWebSessionToList(this); } } private void ConnectComplated() { TraceLog.Trace("ClientSession.ConnectComplated"); m_isConnected = true; m_isConnecting = false; WebSessionEventArgs e = new WebSessionEventArgs(); e.Session = m_webSession; SendPublicKeyToRemote(); OnConnected(e); } private void SendPublicKeyToRemote() { TraceLog.Trace("clientsession SendPublicKeyToRemote"); if (m_rsaCrypto == null) { m_rsaCrypto = new object(); RSABigIntegerUtils.GenRSAKey(); TraceLog.Trace("clientsession RSABigIntegerUtils.GenRSAKey"); } //清空一下,保证逻辑 m_teaKey = null; MessageData message = new MessageData(); message.Data = null; message.Header.Type = (int)SpecialMessageType.PublicKey; if (m_clientSettings.CryptoMessage) { RSAParameters rp = RSABigIntegerUtils.GetRSAParameters(); byte[] data = new byte[2 + rp.Modulus.Length + rp.Exponent.Length]; //string modulus = Convert.ToBase64String(rp.Modulus); //string exp = Convert.ToBase64String(rp.Exponent); byte[] modLenByte = BitConverter.GetBytes((Int16)rp.Modulus.Length); Buffer.BlockCopy(modLenByte, 0, data, 0, 2); Buffer.BlockCopy(rp.Modulus, 0, data, 2, rp.Modulus.Length); Buffer.BlockCopy(rp.Exponent, 0, data, 2 + rp.Modulus.Length, rp.Exponent.Length); message.Data = data; message.Header.Length = data.Length; } else { byte[] data = BitConverter.GetBytes((Int16)6666); message.Data = data; message.Header.Length = data.Length; } Send(message); } private void OnSessionKeyReceive(MessageData message) { TraceLog.Trace("clientsession OnSessionKeyReceive"); if (m_rsaCrypto == null) { return; } byte[] keyBytes = RSABigIntegerUtils.DecryptBytesPrivite(message.Data); m_teaKey = new SogFastXTEAKey(keyBytes); if (Connected != null) { WebSessionEventArgs e = new WebSessionEventArgs(); e.Session = m_webSession; Connected(this, e); } } public override void Send(WebSession webSession, MessageData message) { if (m_teaKey != null && message.Data != null && message.Data.Length > 0) { SogFastXTEA.Encrypt(message.Data, m_teaKey); } m_sendSeq++; ushort crcValue = 0; if (message.Data != null && message.Data.Length > 0) { crcValue = CRC.CRC16(message.Data, message.Data.Length); } message.Header.ServerID = ((uint)m_sendSeq << 16) + crcValue; webSession.SendMessageToQueue(message); } public void Send(MessageData message) { if (m_teaKey != null && message.Data != null && message.Data.Length > 0) { SogFastXTEA.Encrypt(message.Data, m_teaKey); } m_sendSeq++; ushort crcValue = 0; if (message.Data != null && message.Data.Length > 0) { crcValue = CRC.CRC16(message.Data, message.Data.Length); } message.Header.ServerID = ((uint)m_sendSeq << 16) + crcValue; m_webSession.SendMessageToQueue(message); } public void ReceiveMessage() { Queue dataList = m_webSession.GetReceivedDataQueue(); TraceLog.Debug($"ReceiveMessage 111111111111 {dataList.Count}"); for (int i = 0; i < dataList.Count; i++) { MessageData message = dataList.Dequeue(); //加密的消息需要解密 if (m_clientSettings.CryptoMessage && m_teaKey != null && message.Data != null && message.Data.Length > 0) { try { SogFastXTEA.Decrypt(message.Data, m_teaKey); } catch (Exception ex) { //解密失败 TraceLog.Exception(ex); continue; } } try { WebSessionEventArgs e = new WebSessionEventArgs(); e.Message = message; e.Session = m_webSession; OnDataReceived(e); } catch (Exception ex) { // 接收协议失败 TraceLog.Exception(ex); continue; } } TraceLog.Debug($"ReceiveMessage 555555555555 {dataList.Count}"); } public void OnUpdateConnectedSocketError() { TraceLog.Trace("ClientSession.OnUpdateConnectedSocketError close session"); WebSessionEventArgs e = new WebSessionEventArgs(); e.Session = m_webSession; OnDisconnected(e); Close(); } /// /// /// /// public void Close(string reason = "") { //After receiving data processing close m_isConnected = false; CloseWebSocket(); } /// /// /// public void Dispose() { Close(); } } }