using System.Collections; using System.Collections.Generic; using UnityEngine; using CScript.Utilities; using System.Threading; using CScript.Entity; using System; using System.Text; using System.Net; using System.Net.Sockets; using System.IO; using CScript.App; namespace CScript.Net { public class Server : MonoSingleton { //const int DEF_RECV_BUFFER_SIZE = 4096000; const int DEF_RECV_BUFFER_SIZE = 409600 * 2; const int DEF_TRY_CONNECT_TIMES = 3; const int NetConnectTimeout = 10000;// connect wait milliseconds public const int NET_ERROR_UNKNOW_PROTOCOL = 2; //协议错误 public const int NET_ERROR_SEND_EXCEPTION = 1000; //发送异常 public const int NET_ERROR_ILLEGAL_PACKAGE = 1001; //接受到错误数据包 public const int NET_ERROR_ZERO_BYTE = 1002; //收发0字节 public const int NET_ERROR_PACKAGE_TIMEOUT = 1003; //收包超时 public const int NET_ERROR_PROXY_TIMEOUT = 1004; //proxy超时 public const int NET_ERROR_FAIL_TO_CONNECT = 1005; //3次连接不上 public const int NET_ERROR_PROXY_ERROR = 1006; //proxy重启 public const int NET_ERROR_ON_DESTROY = 1007; //结束的时候,关闭网络连接 public const int NET_ERROR_ON_KICKOUT = 25; //被踢了 private List _frontTextAssetList; private List _sideTextAssetList; private List _texture2Ds; private Thread _parseThread; private Thread _drawThread; private Thread _recvThread; private int _dataCount = 10; private List _tempDataValue = new List(); private string[] _tempFrontStr; private string[] _sideFrontStr; public List messageQueue; public delegate void ConnectEventHandler(int result, string reason); public delegate void ExpectPackageEventHandler(); public event ConnectEventHandler OnConnect; public event ConnectEventHandler OnDisconnect; public event ExpectPackageEventHandler OnExpectPackageTimeout; public event ExpectPackageEventHandler OnExpectPackageResume; private IPEndPoint _address; private Socket _clientSocket; private MemoryStream _sendBuffer = new MemoryStream(); private MemoryStream _receiveBuffer = new MemoryStream(DEF_RECV_BUFFER_SIZE); private Queue _sendQueue = new Queue(); private bool _connecting = false; private int _retryTimes = 0;// 重试 private float _lastSendTime = 0; private int _retryTimesTotal = DEF_TRY_CONNECT_TIMES; private int _sendOffset = 0; public bool running { get; set; } public PackageHandler packageHandler = new PackageHandler(null); public void Init(string serverIP, int port) { this._address = new IPEndPoint(IPAddress.Parse(serverIP), port); running = true; } public void Connect(int times = DEF_TRY_CONNECT_TIMES) { if (this._connecting) { return; } if (this._clientSocket != null) { this._clientSocket.Close(); } if (this._address == default(IPEndPoint)) { throw new Exception("Please Init first."); } Debug.Log("DoConnect"); this._connecting = true; this._retryTimes = 0; this.DoConnect(); } protected virtual void RaiseConnected(int result, string reason) { if (_recvThread == null || !_recvThread.IsAlive) { _recvThread = new Thread(Recv); _recvThread.Start(); } ConnectEventHandler handler = OnConnect; if (handler != null) { handler(result, reason); } NetDistribute.Instance.OnConnect(result==0?true:false, reason); } public virtual void RaiseDisonnected(int result, string reason = "") { ConnectEventHandler handler = OnDisconnect; if (handler != null) { handler(result, reason); } NetDistribute.Instance.OnDisconnect(result, reason); } protected virtual void RaiseExpectPackageTimeout() { ExpectPackageEventHandler handler = OnExpectPackageTimeout; if (handler != null) { handler(); } } protected virtual void RaiseExpectPackageResume() { ExpectPackageEventHandler handler = OnExpectPackageResume; if (handler != null) { handler(); } } public bool Connected { get { return (_clientSocket != default(Socket)) ? _clientSocket.Connected : false; } } public void Reset() { this._connecting = false; this.OnConnect = null; this.OnDisconnect = null; this.OnExpectPackageTimeout = null; this.OnExpectPackageResume = null; } void DoConnect() { Debug.Log("NetClient.DoConnect on " + this._address.ToString()); try { if (this._clientSocket != null) { this._clientSocket.Close(); } this._clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); this._clientSocket.Blocking = true; Debug.Log(string.Format("Connect[{0}] to server {1}", this._retryTimes, this._address) + "\n"); IAsyncResult result = this._clientSocket.BeginConnect(this._address, null, null); bool success = result.AsyncWaitHandle.WaitOne(NetConnectTimeout); if (success) { this._clientSocket.EndConnect(result); } } catch (SocketException ex) { if (ex.SocketErrorCode == SocketError.ConnectionRefused) { this.CloseConnection(NET_ERROR_FAIL_TO_CONNECT); } Debug.LogErrorFormat("DoConnect SocketException:[{0},{1},{2}]{3} ", ex.ErrorCode, ex.SocketErrorCode, ex.NativeErrorCode, ex.ToString()); } catch (Exception e) { Debug.Log("DoConnect Exception:" + e.ToString() + "\n"); } if (this._clientSocket.Connected) { this._clientSocket.Blocking = false; this.RaiseConnected(0, "Success"); } else { this._retryTimes++; if (this._retryTimes >= this._retryTimesTotal) { this.RaiseConnected(1, "Cannot connect to server"); } } this._connecting = false; } public void CloseConnection(int errCode) { Debug.LogWarning("CloseConnection(), errorCode: " + errCode.ToString()); this._connecting = false; if (this._clientSocket != null) { this._clientSocket.Close(); } //清空缓冲区 this._receiveBuffer.Position = 0; this._receiveBuffer.SetLength(0); this.packageHandler.Reset(); switch (errCode) { case NET_ERROR_UNKNOW_PROTOCOL: { //致命错误,停止网络服务 this.running = false; } break; case NET_ERROR_FAIL_TO_CONNECT: case NET_ERROR_PROXY_TIMEOUT: case NET_ERROR_PROXY_ERROR: //NetworkManager.Instance.dropCurMessage(); //NetworkManager.Instance.Connect(); break; //离线处理 case NET_ERROR_ON_KICKOUT: case NET_ERROR_ZERO_BYTE: case NET_ERROR_ILLEGAL_PACKAGE: case NET_ERROR_SEND_EXCEPTION: case NET_ERROR_PACKAGE_TIMEOUT: default: this._lastSendTime = 0; this.RaiseDisonnected(errCode); break; } } public void SendTCPMessage(string message) { if (!running) { return; } if (!this.Connected) { //this.receiveBuffer.Position = 0; //this.sendBuffer.Position = sendOffset = 0; this.Connect(); Debug.Log("Connect Server before Send Message!"); return; } _sendQueue.Enqueue(message); if (this._lastSendTime == 0) { this._lastSendTime = Time.time; } } bool KeepConnect() { if (this._connecting) { return false; } if (this._address == null) return false; if (this.Connected) { return true; } if (this._retryTimes < this._retryTimesTotal) { this.Connect(); } return false; } bool ProcessRecv() { bool ret = false; try { if (this._clientSocket.Blocking) { Debug.Log("this.clientSocket.Blocking = true\n"); } bool error = this._clientSocket.Poll(0, SelectMode.SelectError); if (error) { Debug.Log("ProcessRecv Poll SelectError\n"); this.CloseConnection(NET_ERROR_SEND_EXCEPTION); return false; } ret = this._clientSocket.Poll(0, SelectMode.SelectRead); if (ret) { int n = this._clientSocket.Receive(this._receiveBuffer.GetBuffer(), 0, this._receiveBuffer.Capacity, SocketFlags.None); if (n <= 0) { this.CloseConnection(NET_ERROR_ZERO_BYTE); return false; } this.packageHandler.ReceiveData(this._receiveBuffer.GetBuffer(), 0, n); } } catch (Exception e) { Debug.Log("ProcessReceive exception:" + e.ToString() + "\n"); this.CloseConnection(NET_ERROR_ILLEGAL_PACKAGE); return false; } return true; } bool ProcessSend() { bool ret = false; try { if (this._clientSocket.Blocking) { Debug.Log("this.clientSocket.Blocking = true\n"); } bool error = this._clientSocket.Poll(0, SelectMode.SelectError); if (error) { Debug.Log("ProcessSend Poll SelectError\n"); this.CloseConnection(NET_ERROR_SEND_EXCEPTION); return false; } ret = this._clientSocket.Poll(0, SelectMode.SelectWrite); if (ret) { //sendStream exist data if (this._sendBuffer.Position > this._sendOffset) { int bufsize = (int)(this._sendBuffer.Position - this._sendOffset); int n = this._clientSocket.Send(this._sendBuffer.GetBuffer(), this._sendOffset, bufsize, SocketFlags.None); if (n <= 0) { this.CloseConnection(NET_ERROR_ZERO_BYTE); return false; } this._sendOffset += n; if (this._sendOffset >= this._sendBuffer.Position) { this._sendOffset = 0; this._sendBuffer.Position = 0; this._sendQueue.Dequeue();//remove message when send complete } } else { //fetch package from sendQueue if (this._sendQueue.Count > 0) { string message = this._sendQueue.Peek(); byte[] package = Encoding.UTF8.GetBytes(message); this._sendBuffer.Write(package, 0, package.Length); } } } } catch (Exception e) { Debug.Log("ProcessSend exception:" + e.ToString() + "\n"); this.CloseConnection(NET_ERROR_SEND_EXCEPTION); return false; } return true; } void ProceeMessage() { //MessageDistributer.Instance.Distribute(); } void Recv() { while (running) { if (this.KeepConnect()) { ProcessSend(); Debug.Log("开始: " + DateTime.Now.Hour + " :" + DateTime.Now.Minute + " : " + DateTime.Now.Second); if (this.ProcessRecv()) { } Debug.Log("结束: " + DateTime.Now.Hour + " :" + DateTime.Now.Minute + " : " + DateTime.Now.Second); } Thread.Sleep(30); } } private void OnDestroy() { Close(); } public void Close() { if(_recvThread!=null && _recvThread.IsAlive) _recvThread.Abort(); this.running = false; } } }