zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    Stack的一种简单实现
    Allocator中uninitialized_fill等函数的简单实现
    Allocator的简易实现
    编写自己的迭代器
    简单的内存分配器
    vector的简单实现
    异常类Exception
    intent大致使用
    java初识集合(list,set,map)
    php分页
  • 原文地址:https://www.cnblogs.com/CaomaoUnity3d/p/4610586.html
Copyright © 2011-2022 走看看