客戶端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

