在C#网络框架搭建系列(三) ------ 客户端与服务端进行连接文中两端进行连接的时候都有开始接收的代码,那么接收到信息怎么处理呢?这就需要根据双端的协议来进行解析了.在本框架中采用反射进行消息分发,以下是具体实现
嗯~应该还记得 C#网络框架搭建系列(四) ------ 消息发送中协议的大致意思吧这下就要用到啦
1.服务端数据解析
在client.cs中start()方法接收消息后调用ReceiveCallback方法
private void ReceiveCallback(IAsyncResult ar)
{
try
{
if (clientSocket == null || clientSocket.Connected == false) return;
int count = clientSocket.EndReceive(ar);
if (count == 0)
{
Console.WriteLine("收到 [" + GetAdress() + "] 断开链接");
Close();
return;
}
msg.ReadMessage(count, OnProcessMessage);
Start();
}
catch (Exception e)
{
Console.WriteLine("收到 [" + GetAdress() + "] 断开链接 " + e.Message);
Close();
}
}
可以看到接收到消息后调用了MessageHandle中的ReadMessage方法, 该方法里面逐步解析接收到的数据,首先得到该条数据的长度,再依次解析出 RequestCode与 ActionCode,调用processDataCallback方法
public void ReadMessage(int newDataAmount, Action<RequestCode, ActionCode, string> processDataCallback)
{
startIndex += newDataAmount;
while (true)
{
//粘包分包
if (startIndex <= 4) return;
int count = BitConverter.ToInt32(data, 0);
if ((startIndex - 4) >= count)
{
RequestCode requestCode = (RequestCode)BitConverter.ToInt32(data, 4);
ActionCode actionCode = (ActionCode)BitConverter.ToInt32(data, 8);
string s = Encoding.UTF8.GetString(data, 12, count - 8);
processDataCallback(requestCode, actionCode, s);
Array.Copy(data, count + 4, data, 0, startIndex - 4 - count);
startIndex -= (count + 4);
}
else
{
break;
}
}
}
其实也就是client中的 OnProcessMessage方法:
private void OnProcessMessage(RequestCode requestCode, ActionCode actionCode, string data)
{
server.HandleRequest(requestCode, actionCode, data, this);
}
而server中的HandleRequest调用ControllerManager中的分发消息处理方法
//分发消息
public void HandleRequest(RequestCode requestCode, ActionCode actionCode, string data, Client client)
{
controllerManager.HandleRequest(requestCode, actionCode, data, client);
}
大致就是先根据RequestCode得到对应的controller,根据ActionCode得到方法名,然后调用controller中的相应方法,再将处理结果返回给客户端
public void HandleRequest(RequestCode requestCode, ActionCode actionCode, string data, Client client)
{
BaseController controller;
bool isGet = controllerDict.TryGetValue(requestCode, out controller);
if (isGet == false)
{
Console.WriteLine("无法得到[" + requestCode + "]所对应的Controller,无法处理请求"); return;
}
string methodName = Enum.GetName(typeof(ActionCode), actionCode);
MethodInfo mi = controller.GetType().GetMethod(methodName);
if (mi == null)
{
Console.WriteLine("[警告]在Controller[" + controller.GetType() + "]中没有对应的处理方法:[" + methodName + "]"); return;
}
object[] parameters = new object[] { data, client, server };
object o = mi.Invoke(controller, parameters);
if (o == null || string.IsNullOrEmpty(o as string))
{
return;
}
server.SendResponse(client, actionCode,reasonCode, o as string);
}
2.客户端消息处理
与服务端类似,不过只是不是根据RequestCode/ActionCode来解析,而是根据ReturnCode/ReasonCode来解析,这里只是简单的贴下代码
public void HandleReponse(ActionCode actionCode,ReasonCode reasonCode, string data)
{
BaseRequest request;
requestDict.TryGetValue(actionCode,out request);
if (request == null)
{
Debug.Log("无法得到ActionCode[" + actionCode + "]对应的Request类"); return;
}
request.OnResponse(GetReason(reasonCode), data);
}
public override void OnResponse(string reasonCode,string data)
{
string[] strs = data.Split(',');
ReturnCode returnCode = (ReturnCode)int.Parse(strs[0]);
if (returnCode == ReturnCode.Success)
{
Debug.Log("[Login]成功");
GameRoot.Instance.TipText = "[Login]成功";
GameRoot.Instance.isShowTip = true;
}
else if (returnCode == ReturnCode.Fail)
{
Debug.Log("[Login]失败:" + reasonCode);
GameRoot.Instance.TipText = "[Login]失败:" + reasonCode;
GameRoot.Instance.isShowTip = true;
}
}
总算告一段落,接下来就是QFramework的学习了,然后再是小游戏的教程,成就感满满.
愿我的文章能帮到看到的童鞋~
框架下载地址:
https://github.com/webloverand/ServerFramework
搭建系列文章地址:
https://blog.csdn.net/dengshunhao/article/details/81561174