客户端关闭连接

NetManager中添加CloseConnection方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void ReceiveCallback(IAsyncResult ar)
{
try
{
Socket socket = (Socket)ar.AsyncState;
int count = socket.EndReceive(ar);
if(count <= 0)
{
//说明服务器已经关闭链接
CloseConnection();//+++
return;
}
//...
}
/// <summary>
/// 关闭与远程服务器的链接
/// </summary>
/// <param name="normal">是否正常关闭</param>
public void CloseConnection(bool normal = true)
{
if(m_Socket == null || m_IsConnecting) return;

//根据是否正常关闭调整消息发送队列,暂时省略

SecretKey = "";
m_Socket.Close();
FirstEvent(NetEvent.Close,normal.ToString());
Debug.Log("CloseSocket");
}

修改MsgBaseEncode方法和Decode方法,在客户端中,不需要通过判断消息类型来确定公钥私钥,所以我们删除部分代码。并添加上判断是否持有私钥的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public static byte[] Encode(MsgBase msg)
{
string secret;//+++
if(string.IsNullOrEmpty(NetManager.Instance.SecretKey))//+++
{
secret = NetManager.Instance.PublicKey;//+++
}
else
{
secret = NetManager.Instance.SecretKey;//+++
}
using(MemoryStream ms = new MemoryStream())
{
//使用ProtoBuf将协议内容序列化
Serializer.Serialize(ms, msg);
byte[] bytes = ms.ToArray();

bytes = AES.AESEncrypt(bytes, secret);
return bytes;
}
}
public static MsgBase? Decode(ProtocolEnum protocol,byte[] bytes,int offset,int count)
{
if (count <= 0)
{
Debug.LogError("协议解密出错,数据长度为0");
return null;
}
string secret;//+++/
if (string.IsNullOrEmpty(NetManager.Instance.SecretKey))//+++
{
secret = NetManager.Instance.PublicKey;//+++
}
else
{
secret = NetManager.Instance.SecretKey;//+++
}
try
{
byte[] newbytes = new byte[count];
Array.Copy(bytes, offset, newbytes, 0, count);

newbytes = AES.AESDecrypt(newbytes, secret);
using (MemoryStream ms = new MemoryStream(newbytes,0,newbytes.Length))
{
//...
}
}
//...
}

客户端解析数据

客户端在回调里解析数据,基本流程和服务端差不多,由于客户端回调是在多线程里面调用的,所以解析出来的数据需要先缓存再解析。

NetManager里面添加m_MsgListm_MsgCount,并在初始化时创建好。注意m_MsgCount不计录心跳包的消息,所以消息列表的长度不是m_MsgList的Count,一开始所有的消息都会让m_MsgCount + 1,但客户端分发消息时一旦发现是心跳包消息,会让m_MsgCount - 1

1
2
3
4
5
6
7
8
9
10
   private List<MsgBase> m_MsgList;
//消息列表长度
private int m_MsgCount;
void InitState()
{
//...
m_MsgList = new List<MsgBase>();
m_MsgCount = 0;
}

修改NetManager里面的OnReceiveData方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/// <summary>
/// 对接收的数据进行处理
/// </summary>
void OnReceiveData()
{
if(m_ReadBuff.Length <=4 || m_ReadBuff.ReadIdx<0) return;
int readIdx = m_ReadBuff.ReadIdx;
byte[] bytes = m_ReadBuff.Bytes;
int bodyLength = BitConverter.ToInt32(bytes, readIdx);
if(m_ReadBuff.Length < bodyLength + 4)//是个分包
{
return;
}
m_ReadBuff.ReadIdx += 4;
int nameCount;
ProtocolEnum protocol = MsgBase.DecodeName(m_ReadBuff.Bytes, m_ReadBuff.ReadIdx, out nameCount);
if(protocol == ProtocolEnum.None)
{
Debug.LogError("OnReceiveData MsgBase.DecodeName fail");
CloseConnection();
return;
}
m_ReadBuff.ReadIdx += nameCount;
//解析协议内容
int bodyCount = bodyLength - nameCount;
try
{
MsgBase msg = MsgBase.Decode(protocol, m_ReadBuff.Bytes, m_ReadBuff.ReadIdx, bodyCount);
if (msg == null)
{
Debug.LogError("解析协议内容出错");
CloseConnection();
return;
}
m_ReadBuff.ReadIdx += bodyCount;
m_ReadBuff.CheckAndMoveBytes();
//协议具体的操作
lock(m_MsgList)
{
m_MsgList.Add(msg);//添加消息列表
}
m_MsgCount++;//添加消息数量
if(m_ReadBuff.Length > 4)//处理粘包
{
OnReceiveData();
}
}
catch (Exception ex)
{
Debug.LogError("OnReceiveData MsgBase.Decode fail" + ex);
CloseConnection();
}

}