123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433 |
- 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<Server>
- {
- //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<string> _frontTextAssetList;
- private List<string> _sideTextAssetList;
- private List<Texture2D> _texture2Ds;
- private Thread _parseThread;
- private Thread _drawThread;
- private Thread _recvThread;
- private int _dataCount = 10;
- private List<int> _tempDataValue = new List<int>();
- private string[] _tempFrontStr;
- private string[] _sideFrontStr;
- public List<byte[]> 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<string> _sendQueue = new Queue<string>();
- 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;
- }
- }
- }
|