文章目录
1.首先我们将消息分为两类
1.1 普通消息
直接发送给游戏服务器,发送给黄色的Realm网关负载均衡服务器
1.2 ActLocation的消息
必须要经过Gate网关转发的消息,图中绿色的部分
转发到具体的Map游戏服务器,然后由游戏服务器处理之后再返回到Gate网关,然后将消息返回到客户端
2.编写网络通讯消息
2.1 进入LoginHelper.cs编写代码
public static async ETTask LoginTest(Scene zoneScene,string address)
{
try
{
//客户端与服务端交互是使用Session
Session session = null;
try
{
//创建连接用的Session
session = zoneScene.GetComponent<NetKcpComponent>().Create(NetworkHelper.ToIPEndPoint(address));
}
finally
{
}
}
catch (Exception e)
{
//异常就log出去
Log.Error(e.ToString());
}
}
2.2 进入Proto文件夹
2.3 普通消息写在OuterMessage.proto
编写一个游戏 客户端 发送给 服务端(Realm网关负载均衡服务器)的第一条普通消息
普通消息是不经过网关服务器的,所以和 服务器 是直连关系
这样的普通消息写在OuterMessage.proto里面
2.3.1需要回复的消息
如果我们需要服务器返回我们客户端的消息,则我们应该定义一个RpcId,同时后面加上// IRequest
,代表这条消息服务器必须要回复
//response R2C_LoginTest
,代表指定一个回复类型
名字这里是C2R,代表 客户端 到 Realm网关负载均衡服务器
注意:‘=’ 旁边得有空格
//ResponseType R2C_LoginTest
message C2R_LoginTest // IRequest
{
int32 RpcId = 90;
string Account = 1;
string Password = 2;
}
message R2C_LoginTest // IResponse
{
int32 RpcId = 90;
int32 Error = 91;
string Message = 92;
string GateAddress = 1;
string key = 2;
}
2.3.2 不需要回复的普通消息
message C2R_SayHello // IMessage
{
string Hello = 1;
}
message R2C_SayGoodBye // IMessage
{
string GoodBye = 1;
}
2.4 进入LoginHelper.cs完善代码
2.4.1 消息请求
public static async ETTask LoginTest(Scene zoneScene,string address)
{
try
{
//客户端与服务端交互是使用Session
Session session = null;
R2C_LoginTest r2C_LoginTest = null;
try
{
//创建连接用的Session
session = zoneScene.GetComponent<NetKcpComponent>().Create(NetworkHelper.ToIPEndPoint(address));
{
//调用Call命令发送登录请求 需要回复 await 就是一直在等待回复
r2C_LoginTest = (R2C_LoginTest)await session.Call(new C2R_LoginTest() {
Account = "", Password = "" });
//等待到服务器回复
Log.Debug(r2C_LoginTest.key);
//send发送消息给服务器 不需要回复
session.Send(new C2R_SayHello() {
Hello = "Hello Server!" });
}
}
finally
{
}
}
catch (Exception e)
{
//异常就log出去
Log.Error(e.ToString());
}
}
2.4.2 回复消息
创建一个文件夹,以及一个脚本,专门处理这个事件
记得名字后面加Handler,代表处理
这是ET命名规范
回复 C2R_LoginTest
namespace ET
{
//这里继承了AMRpcHandler,这个类就具有了向客户端回复普通消息的能力
[MessageHandler]
internal class C2R_LoginTestHandler : AMRpcHandler<C2R_LoginTest, R2C_LoginTest>
{
//session表示服务器的session , request是客户端的,response是服务器的,reply是Act委托
protected override async ETTask Run(Session session, C2R_LoginTest request, R2C_LoginTest response, Action reply)
{
//设置回复的key
response.key = "111111111111111";
//回复的Act委托
reply();
//异步变同步
await ETTask.CompletedTask;
}
}
}
**回复 C2R_SayHello **
namespace ET
{
[MessageHandler]
public class C2R_SayHelloHandler : AMHandler<C2R_SayHello>
{
protected override async ETTask Run(Session session, C2R_SayHello message)
{
Log.Debug(message.Hello);
//这里我们主动让服务器发送一条消息给客户端
session.Send(new R2C_SayGoodBye() {
GoodBye = "byebye" });
await ETTask.CompletedTask;
}
}
}
至此,我们创建了两个脚本来分别处理两个消息
2.5进入Client编写客户端接受消息
我们这里处理的是
R2C_SayGoodBye 服务端发送给客户端的消息
namespace ET
{
[MessageHandler]
internal class R2C_SayGoodByeHander : AMHandler<R2C_SayGoodBye>
{
protected override async ETTask Run(Session session, R2C_SayGoodBye message)
{
Log.Debug(message.GoodBye);
await ETTask.CompletedTask;
}
}
}
3.调用我们编写的网络通讯代码
我们进入我们在 LoginHelper.cs 编写的代码
我们找到调用Login的地方
我们取消默认的Login函数的调用
改为调用我们的LoginTest
public static void OnLoginClickHandler(this DlgLogin self)
{
//LoginHelper.Login(
// self.DomainScene(),
// ConstValue.LoginAddress,
// self.View.E_AccountInputField.GetComponent<InputField>().text,
// self.View.E_PasswordInputField.GetComponent<InputField>().text).Coroutine();
//我们注释掉默认的Login函数,使用我们自己的
LoginHelper.LoginTest(self.DomainScene(),ConstValue.LoginAddress).Coroutine();
}
4.运行代码
我们首先全部生成解决方法
然后BuildCode
启动服务器,运行Unity
然后运行Unity
我们来分析结果
Unity客户端Log
1.我们发送了一条C2R_LoginTest的消息
2.我们发送了一条R2C_LoginTest的语句
3.我们输出了1111111
4.我们发送了一条C2R_SayHello的语句
5.我们发送了一条R2C_SayGoodBye的语句
6.我们输出了byebye
我们进入服务器的Logs
5.总结
我们现在已经学会了普通消息的发送
不仅仅是需要服务器响应的消息
还有不需要回复的消息
我们都使用了