123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483 |
- using UnityEngine;
- using System.Collections;
- using System.Collections.Generic;
- using System;
- using System.Net;
- using System.Net.Sockets;
- using System.Text;
- using System.IO;
- namespace Engine.Net
- {
- /// <summary>服务器类型</summary>
- public enum ESockeType
- {
- /// <summary>游戏服务器</summary>
- Game = 0,
- }
- /// <summary>服务器类型</summary>
- public enum ESocketConnectType
- {
- /// <summary>连接类型</summary>
- TCP = 0,
- UDP = 1,
- }
- /// <summary>客户端socket对象</summary>
- public class NetSocket
- {
- /// <summary>连接对象</summary>
- public Socket mSocket = null;
- /// <summary>接收数据的位置。</summary>
- private int nRecvPos = 0;
- /// <summary>保存接受到的数据</summary>
- private byte[] arrRecvBuff;
- /// <summary>接受到的消息</summary>
- private Queue<NetMsg> mQueueRecvMsg;
- /// <summary>消息日志对象</summary>
- public NetMsgLog netMsgLog = new NetMsgLog();
- /// <summary>对发送的优化,增加处理:多线程调用SendMsg时的处理,BeginSend和EndSend的串行处理,增加发送缓冲区</summary>
- private System.Object mSendLock = new System.Object();
- /// <summary>需要发送的内容</summary>
- private byte[] mSendBuff;
- /// <summary>发送的长度</summary>
- private int nSendBuffDataLen;
- /// <summary>表示已经调用了BeginSend,正在等待结束</summary>
- private bool bSendPending = false;
- /// <summary>服务器类型</summary>
- //public ESockeType socketType = ESockeType.Game;
- /// <summary>连接类型</summary>
- public ESocketConnectType socketConnectType = ESocketConnectType.TCP;
- /// <summary>构造函数</summary>
- public NetSocket(ESockeType type, ESocketConnectType connectType)
- {
- //socketType = type;
- socketConnectType = connectType;
- arrRecvBuff = new byte[NetMsg.MAX_MSG_LEN];
- nRecvPos = 0;
- mQueueRecvMsg = new Queue<NetMsg>();
- mSendBuff = new byte[NetMsg.MAX_MSG_LEN];
- nSendBuffDataLen = 0;
- }
- #region 创建和断开连接
- /// <summary>创建Socket连接</summary>
- public bool Connect(string strIp, int nPort)
- {
- //如果存在连接线断开
- if (mSocket != null)
- {
- DoDisconnect(false);
- }
- try
- {
- if(socketConnectType == ESocketConnectType.TCP)
- {
- mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- }
- else if(socketConnectType == ESocketConnectType.UDP)
- {
- mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
- }
- CDebug.Log("Connect " + strIp + " "+nPort);
- mSocket.BeginConnect(strIp, nPort, new AsyncCallback(ConnectCallback), mSocket);
- //Debug.Log(mSocket.ReceiveBufferSize + " " + mSocket.SendBufferSize);
- mSocket.ReceiveBufferSize = 204800;
- mSocket.SendBufferSize = 204800;
- //Debug.Log(mSocket.ReceiveBufferSize + " " + mSocket.SendBufferSize);
- }
- catch (SocketException e)
- {
- SendDisconnectMsg(true);
- CDebug.LogError(e.Message);
- return false;
- }
- return true;
- }
- /// <summary>Socket连接完成</summary>
- private void ConnectCallback(IAsyncResult ar)
- {
- try
- {
- Socket client = (Socket)ar.AsyncState;
- client.EndConnect(ar);
- nRecvPos = 0;
- if (!StartRecvMsg())
- {
- DoDisconnect();
- }
- SendConnectGSuccess();
- }
- catch (SocketException e)
- {
- CDebug.LogError(e.Message);
- mSocket.Close();
- mSocket = null;
- }
- }
- /// <summary>Socket对象是否连接中</summary>
- public bool IsConnected()
- {
- return (mSocket == null) ? false : mSocket.Connected;
- }
- /// <summary>发送Socket连接失败的消息</summary>
- private void SendDisconnectMsg(bool bReceiveDisconnMsg = true)
- {
- if (bReceiveDisconnMsg == true)
- {
- NetMsg msg = new NetMsg(NetCode.MSG_CONE_CONNECT_FAIL);
- //msg.arrData.WriteInt((int)socketType);
- mQueueRecvMsg.Enqueue(msg);
- }
- }
- /// <summary>服务器连接成功</summary>
- private void SendConnectGSuccess()
- {
- NetMsg msg = new NetMsg(NetCode.MSG_CONE_CONNECT_SUCCESS);
- //msg.arrData.WriteInt((int)socketType); ;
- mQueueRecvMsg.Enqueue(msg);
- }
- #endregion
- #region 接受消息相关
- /// <summary>获得一个已经接受到的消息</summary>
- public NetMsg RecvMsg()
- {
- if (mQueueRecvMsg.Count == 0)
- return null;
- NetMsg msg = null;
- try
- {
- msg = mQueueRecvMsg.Dequeue();
- }
- catch
- { }
- return msg;
- }
- /// <summary>开始接受消息</summary>
- private bool StartRecvMsg()
- {
- if (mSocket == null)
- return false;
- try
- {
- SocketError err;
- mSocket.BeginReceive(arrRecvBuff, nRecvPos, arrRecvBuff.Length - nRecvPos, SocketFlags.None, out err, new AsyncCallback(RecvCallback), this);
- }
- catch
- {
- return false;
- }
- return true;
- }
- /// <summary>消息接受完成</summary>
- private void RecvCallback(IAsyncResult ar)
- {
- int nRecv = 0;
- try
- {
- if (mSocket != null)
- {
- SocketError err;
- nRecv = mSocket.EndReceive(ar, out err);
- }
- else
- {
- SendDisconnectMsg();
- return;
- }
- }
- catch (System.Exception e)
- {
- //出现异常
- #if UNITY_EDITOR
- CDebug.LogError("recv msg error "+ e.Message + e.StackTrace);
- #endif
- SendDisconnectMsg();
- return;
- }
-
- //如果接受的字节数是0,断开连接
- if (nRecv == 0)
- {
- DoDisconnect(true, "Common disconnect");
- return;
- }
- //CDebug.Log("字节长度 " + nRecv);
- //追加接受的到字节
- nRecvPos += nRecv;
- //循环读取接受到的全部消息内容
- do
- {
- if (!IsConnected())
- break;
- NetMsg msg = null;
- if (ParseMsg(ref arrRecvBuff, ref nRecvPos, ref msg))
- {
- //添加接收时序
- UpdateMsgResSequence();
- //解析成功吧消息添加到队列中
- mQueueRecvMsg.Enqueue(msg);
- //接受消息日志
- netMsgLog.ResMessage(msg);
- }
- else
- {
- //解析失败
- break;
- }
- } while (true);
- //继续挂起接收消息
- StartRecvMsg();
- }
- /// <summary>解析消息</summary>
- private bool ParseMsg(ref byte[] buff, ref int nLen, ref NetMsg msg)
- {
- //当前数据长度小于固定长度,返回失败
- if (nLen < NetMsg.MIN_MSG_LEN)
- return false;
- msg = NetMsg.OnCreateNetMsg(buff);
- //获得当前消息的长度
- int nMsgSize = msg.arrData.ReadInt();
- //判断消息长度是否合法
- if (nMsgSize < NetBytes.INT32_LEN || nMsgSize > NetMsg.MAX_MSG_LEN)
- {
- //消息长度非法,断开连接
- DoDisconnect(true, "Invalid msg len " + nMsgSize);
- return false;
- }
- //如果当前消息不完整,失败
- if (nLen < nMsgSize)
- {
- CDebug.Log("如果当前消息不完整 " + nLen + " " + nMsgSize);
- return false;
- }
- if (!msg.ReadMessage(buff, nMsgSize))
- {
- RemoveBuff(ref buff, ref nLen, nMsgSize);
- CDebug.Log("读取失败 " + nLen + " " + nMsgSize);
- return false;
- }
- //清除该消息的缓冲区
- RemoveBuff(ref buff, ref nLen, nMsgSize);
- return true;
- }
- /// <summary>清理消息buff</summary>
- private void RemoveBuff(ref byte[] buff, ref int nLen, int nSize)
- {
- if (nSize <= nLen)
- {
- int nCopyLen = nLen - nSize;
- for (int i = 0; i < nCopyLen; ++i)
- {
- buff[i] = buff[i + nSize];
- }
- nLen -= nSize;
- }
- }
- /// <summary>断开连接</summary>
- public void DoDisconnect(bool bReceiveDisconnMsg = true, string strReason = null)
- {
- if (!IsConnected())
- {
- return;
- }
- if (!string.IsNullOrEmpty(strReason))
- {
- CDebug.LogError("Disconnect connection: " + strReason);
- }
- if (mSocket != null)
- {
- SendDisconnectMsg(bReceiveDisconnMsg);
- CDebug.Log("尝试断开socket链接" + mSocket.Connected);
- try
- {
- mSocket.Disconnect(true);
- mSocket.Close();
- }
- catch
- {
- CDebug.LogError("DisConnected");
- }
- mSocket = null;
- nRecvPos = 0;
- }
- }
- /// <summary>修改接受消息的消息时序</summary>
- private void UpdateMsgResSequence()
- {
- //目前版本消息时序没有添加验证
- }
- #endregion
- #region 发送消息相关
- /// <summary>发送消息</summary>
- public bool SendMsg(NetMsg msg)
- {
- if (mSocket == null)
- return false;
- lock (mSendLock)
- {
- byte[] buff = null;
- buff = msg.FastPackMsg();
- if (buff == null)
- return false;
- //修改发送消息的消息时序
- UpdateMsgSendSequence();
- int nNewSendBuffDataLen = nSendBuffDataLen + buff.Length;
- if (mSendBuff.Length < nNewSendBuffDataLen)
- {
- System.Array.Resize<byte>(ref mSendBuff, nNewSendBuffDataLen * 2);
- }
- System.Array.Copy(buff, 0, mSendBuff, nSendBuffDataLen, buff.Length);
- nSendBuffDataLen += buff.Length;
- //发送日志
- netMsgLog.SendMessage(msg);
- SendDataInBuffer_inLock();
- }
- return true;
- }
- /// <summary>发送消息</summary>
- private void SendDataInBuffer_inLock()
- {
- if (bSendPending)
- return;
- try
- {
- if (nSendBuffDataLen == 0)
- return;
- SocketError err;
- mSocket.BeginSend(mSendBuff, 0, nSendBuffDataLen, SocketFlags.None, out err, SendCallback, this);
- if (err != SocketError.Success && err != SocketError.WouldBlock)
- {
- DoDisconnect(true, "BeginSend error " + err.ToString());
- return;
- }
- bSendPending = true;
- }
- catch (Exception e)
- {
- if (e is SocketException)
- {
- SocketException es = (SocketException)e;
- if (es.SocketErrorCode == SocketError.Success
- || es.SocketErrorCode == SocketError.WouldBlock)
- {
- return;
- }
- }
- DoDisconnect(true, "BeginSend excption: " + e.Message);
- return;
- }
- }
- /// <summary>发送消息完成</summary>
- private void SendCallback(IAsyncResult ar)
- {
- lock (mSendLock)
- {
- bSendPending = false;
- if (mSocket == null)
- return;
- try
- {
- SocketError err;
- int nSendLen = mSocket.EndSend(ar, out err);
- if (nSendLen <= 0)
- {
- if (err != SocketError.Success && err != SocketError.WouldBlock)
- {
- DoDisconnect(true, "EndSend error " + err.ToString());
- }
- return;
- }
- RemoveBuff(ref mSendBuff, ref nSendBuffDataLen, nSendLen);
- if (nSendBuffDataLen > 0)
- {
- SendDataInBuffer_inLock();
- }
- }
- catch (Exception e)
- {
- //出现异常,可以判断一下是否需要断开连接
- if (e is SocketException)
- {
- SocketException es = (SocketException)e;
- if (es.SocketErrorCode == SocketError.Success
- || es.SocketErrorCode == SocketError.WouldBlock)
- {
- return;
- }
- }
- DoDisconnect(true, "EndSend Exception " + e.Message);
- }
- }
- }
-
- /// <summary>修改发送消息的消息时序</summary>
- private void UpdateMsgSendSequence()
- {
- //目前版本消息时序没有添加验证
- }
- #endregion
- }
- }
|