Netty游戏服务器之六服务端登录消息处理
客户端unity3d已经把消息发送到netty服务器上了,那么ServerHandler类的public void channelRead(ChannelHandlerContext ctx, Object msg) 就会触发,
所有我们在这里吧消息发送至各自处理的类,这里呢我根据不同的消息类型,定义了不同的消息分派类。如login消息就制定LoingDispatch类,专门处理登录这个模块。
public class LoginProtocol { /* * Login_Area * **/ public static final int Area_LoginRequest = 0; // 登陆请求 public static final int Area_LoginResponse = 1; //登录应答 /* * Login_Command * **/ public static final int Login_InvalidMessage = 0;//无效消息 public static final int Login_InvalidUsername = 1;//无效用户名 public static final int Login_InvalidPassword = 2;//密码错误 public static final int Login_Succeed = 10;//登陆成功 }
public class LoginDispatch { private static LoginDispatch instance = new LoginDispatch(); public static LoginDispatch getInstance() { return instance; } public void dispatch(ChannelHandlerContext ctx, SocketModel message) { switch (message.getArea()) { case LoginProtocol.Area_LoginRequest: //处理登录的事务 break; default: break; } } }
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception//当客户端发送数据到服务器会触发此函数 { SocketModel message = (SocketModel) msg; switch (message.getType()) { case TypeProtocol.TYPE_LOGIN: LoginDispatch.getInstance().dispatch(ctx, message);//分派登录消息 break; case TypeProtocol.TYPE_WIZARD: WizardDispatch.getInstance().dispatch(ctx, message); break; case TypeProtocol.TYPE_USER: UserDispatch.getInstance().dispatch(ctx, message); break; case TypeProtocol.TYPE_BATTLE: BattleDispatch.getInstance().dispatch(ctx, message); default: break; }
接着我们处理登录事务搞出点事情,你也可以尝试这打印几句话,看客户端和服务端能否正常的通信,如果可以请看下面:
测试好了之后,我们要把客户端发送过来的消息,其中捎带的账号和密码给解析出来,然后放到数据库中验证,再把是否成功类型赋给SocketModel的Command,返发送给客户端。
这样客户端就根据command的值做不同的处理。
当然这只是我个人的观点,有问题可以和我谈谈。
这个你们应该可以自己写了吧,无非就是一些逻辑的判断,通过这句ctx.writeAndFlush(消息(SocketModel));发送给客户端。
public class LoginDispatch { private static LoginDispatch instance = new LoginDispatch(); public static LoginDispatch getInstance() { return instance; } public User user = null; public Wizard wizard = null; public void dispatch(ChannelHandlerContext ctx, SocketModel message) { switch (message.getArea()) { case LoginProtocol.Area_LoginRequest: LoginResponse(ctx,message); break; default: break; } } /* * **检测用户登录是否密码错误,用户名不存在等,返回int对应的不同类型 */ public int LoginCheck(ChannelHandlerContext ctx,SocketModel request) { List<String> message = request.getMessage(); String username = message.get(0); String password = message.get(1); //System.out.println(username); //System.out.println(password); if (message.isEmpty()) { return LoginProtocol.Login_InvalidMessage; }else{ if (UserMySQL.getInstance().usernameExit(username)) { user = UserMySQL.getInstance().userExit(username, password,ctx.channel()); if (user != null){ return LoginProtocol.Login_Succeed; }else{ return LoginProtocol.Login_InvalidPassword; } }else{ return LoginProtocol.Login_InvalidUsername; } } } public void LoginResponse(ChannelHandlerContext ctx,SocketModel request) { SocketModel response = new SocketModel(); int command = LoginCheck(ctx, request); response.setType(TypeProtocol.TYPE_LOGIN); response.setArea(LoginProtocol.Area_LoginResponse); response.setCommand(command); response.setMessage(request.getMessage()); ctx.writeAndFlush(response); if (command == LoginProtocol.Login_Succeed) { LoginUser(ctx,request);//如果成功就登陆用户,并开始新手向导 } } /** * 登陆用户,并开始新手向导 * @param ctx */ public void LoginUser(ChannelHandlerContext ctx,SocketModel socketModel) { user = UserMySQL.getInstance().initUser(User.getUserByChannel(ctx.channel())); user.setWizard(WizardMySQL.getInstance().initWizard(user.getUserID())); SocketModel message = new SocketModel(); message.setType(TypeProtocol.TYPE_WIZARD); message.setArea(WizardProtocol.Wizard_Create_Request); message.setCommand(user.getWizard().getStepIndex()); message.setMessage(null); ctx.writeAndFlush(message); } }
这里是我写的分派类,思路大概就是这样。注意我这是有数据库的,需要去数据库里面验证正确性。你们可以自己写,因为每个人都不同。
我推荐用phpamdin来管理mysql数据库,简单方便。
里面存有4个账号
好了运行试试,我随便输一个账号,
可以看到服务器收到了客户端发送的账户密码,
我们在看看客户端,由于我写了登陆成功的话就跳转场景,并在console中可以看到“登陆成功”的debug