原本不打算把登录拿出来写的,但是阅读登录部分的代码的时候发现登录和注册还不太一回事,因为登录涉及到分配baseapp的ip,负载均衡的实现,所以水一下。
流程图:
和上次一样,先是找unity控件
找到ui.cs下的login
1 void login() 2 { 3 Common.DEBUG_MSG("login is Click, name=" + username.input.text + ", password=" + password.input.text + "!"); 4 5 log_label.obj.text = "请求连接服务器..."; 6 log_label.obj.color = UnityEngine.Color.green; 7 if(username.input.text == "" || username.input.text.Length > 30) 8 { 9 log_label.obj.text = "用户名或者邮箱地址不合法。"; 10 log_label.obj.color = UnityEngine.Color.red; 11 Common.WARNING_MSG("ui::login: invalid username!"); 12 return; 13 } 14 15 if(password.input.text.Length < 6 || password.input.text.Length > 16) 16 { 17 log_label.obj.text = "密码不合法, 长度应该在6-16位之间。"; 18 log_label.obj.color = UnityEngine.Color.red; 19 Common.WARNING_MSG("ui::login: invalid reg_password!"); 20 return; 21 } 22 23 KBEngine.Event.fireIn("login", username.input.text, password.input.text, System.Text.Encoding.UTF8.GetBytes("kbengine_unity_warring")); 24 log_label.obj.text = "连接成功,等待处理请稍后..."; 25 }
根据上篇文章思路找到Kbengine.cs下的login_loginapp
/* 登录到服务端(loginapp), 登录成功后还必须登录到网关(baseapp)登录流程才算完毕 */ public void login_loginapp(bool noconnect) { if(noconnect) { reset(); _networkInterface.connectTo(_args.ip, _args.port, onConnectTo_loginapp_callback, null); } else { Dbg.DEBUG_MSG("KBEngine::login_loginapp(): send login! username=" + username); Bundle bundle = Bundle.createObject(); bundle.newMessage(Message.messages["Loginapp_login"]); bundle.writeInt8((sbyte)_args.clientType); bundle.writeBlob(KBEngineApp.app._clientdatas); bundle.writeString(username); bundle.writeString(password); bundle.send(_networkInterface); } }
去服务器的loginapp项目找login
//------------------------------------------------------------------------------------- void Loginapp::login(Network::Channel* pChannel, MemoryStream& s) { AUTO_SCOPED_PROFILE("login"); COMPONENT_CLIENT_TYPE ctype; CLIENT_CTYPE tctype = UNKNOWN_CLIENT_COMPONENT_TYPE; std::string loginName; std::string password; std::string datas; // 前端类别 s >> tctype; ctype = static_cast<COMPONENT_CLIENT_TYPE>(tctype); // 附带数据 s.readBlob(datas); // 帐号登录名 s >> loginName; // 密码 s >> password; loginName = KBEngine::strutil::kbe_trim(loginName); if(loginName.size() == 0) { INFO_MSG("Loginapp::login: loginName is NULL.\n"); _loginFailed(pChannel, loginName, SERVER_ERR_NAME, datas, true); s.done(); return; } if(loginName.size() > ACCOUNT_NAME_MAX_LENGTH) { INFO_MSG(fmt::format("Loginapp::login: loginName is too long, size={}, limit={}.\n", loginName.size(), ACCOUNT_NAME_MAX_LENGTH)); _loginFailed(pChannel, loginName, SERVER_ERR_NAME, datas, true); s.done(); return; } if(password.size() > ACCOUNT_PASSWD_MAX_LENGTH) { INFO_MSG(fmt::format("Loginapp::login: password is too long, size={}, limit={}.\n", password.size(), ACCOUNT_PASSWD_MAX_LENGTH)); _loginFailed(pChannel, loginName, SERVER_ERR_PASSWORD, datas, true); s.done(); return; } if(datas.size() > ACCOUNT_DATA_MAX_LENGTH) { INFO_MSG(fmt::format("Loginapp::login: bindatas is too long, size={}, limit={}.\n", datas.size(), ACCOUNT_DATA_MAX_LENGTH)); _loginFailed(pChannel, loginName, SERVER_ERR_OP_FAILED, datas, true); s.done(); return; } // 首先必须baseappmgr和dbmgr都已经准备完毕了。 Components::ComponentInfos* baseappmgrinfos = Components::getSingleton().getBaseappmgr(); if(baseappmgrinfos == NULL || baseappmgrinfos->pChannel == NULL || baseappmgrinfos->cid == 0) { datas = ""; _loginFailed(pChannel, loginName, SERVER_ERR_SRV_NO_READY, datas, true); s.done(); return; } Components::ComponentInfos* dbmgrinfos = Components::getSingleton().getDbmgr(); if(dbmgrinfos == NULL || dbmgrinfos->pChannel == NULL || dbmgrinfos->cid == 0) { datas = ""; _loginFailed(pChannel, loginName, SERVER_ERR_SRV_NO_READY, datas, true); s.done(); return; } if(!g_kbeSrvConfig.getDBMgr().allowEmptyDigest) { std::string clientDigest; if(s.length() > 0) s >> clientDigest; if(clientDigest.size() > 0) { if(clientDigest != digest_) { INFO_MSG(fmt::format("Loginapp::login: loginName({}), digest not match. curr({}) != dbmgr({})\n", loginName, clientDigest, digest_)); datas = ""; _loginFailed(pChannel, loginName, SERVER_ERR_ENTITYDEFS_NOT_MATCH, datas, true); return; } } else { //WARNING_MSG(fmt::format("Loginapp::login: loginName={} no check entitydefs!\n", loginName)); } } s.done(); if(shuttingdown_ != SHUTDOWN_STATE_STOP) { INFO_MSG(fmt::format("Loginapp::login: shutting down, {} login failed!\n", loginName)); datas = ""; _loginFailed(pChannel, loginName, SERVER_ERR_IN_SHUTTINGDOWN, datas, true); return; } if(initProgress_ < 1.f) { datas = fmt::format("initProgress: {}", initProgress_); _loginFailed(pChannel, loginName, SERVER_ERR_SRV_STARTING, datas, true); return; } // 把请求交由脚本处理 SCOPED_PROFILE(SCRIPTCALL_PROFILE); PyObject* pyResult = PyObject_CallMethod(getEntryScript().get(), const_cast<char*>("onReuqestLogin"), const_cast<char*>("ssby#"), loginName.c_str(), password.c_str(), tctype, datas.c_str(), datas.length()); if(pyResult != NULL) { bool login_check = true; if(PySequence_Check(pyResult) && PySequence_Size(pyResult) == 5) { char* sname; char* spassword; char *extraDatas; Py_ssize_t extraDatas_size = 0; SERVER_ERROR_CODE error; if(PyArg_ParseTuple(pyResult, "H|s|s|b|y#", &error, &sname, &spassword, &tctype, &extraDatas, &extraDatas_size) == -1) { ERROR_MSG(fmt::format("Loginapp::login: {}.onReuqestLogin, Return value error! loginName={}\n", g_kbeSrvConfig.getLoginApp().entryScriptFile, loginName)); login_check = false; _loginFailed(pChannel, loginName, SERVER_ERR_OP_FAILED, datas, true); } if(login_check) { loginName = sname; password = spassword; if (extraDatas && extraDatas_size > 0) datas.assign(extraDatas, extraDatas_size); else SCRIPT_ERROR_CHECK(); } if(error != SERVER_SUCCESS) { login_check = false; _loginFailed(pChannel, loginName, error, datas, true); } if(loginName.size() == 0) { INFO_MSG("Loginapp::login: loginName is NULL.\n"); _loginFailed(pChannel, loginName, SERVER_ERR_NAME, datas, true); s.done(); return; } } else { ERROR_MSG(fmt::format("Loginapp::login: {}.onReuqestLogin, Return value error, must be errorcode or tuple! loginName={}\n", g_kbeSrvConfig.getLoginApp().entryScriptFile, loginName)); login_check = false; _loginFailed(pChannel, loginName, SERVER_ERR_OP_FAILED, datas, true); } Py_DECREF(pyResult); if(!login_check) return; } else { SCRIPT_ERROR_CHECK(); _loginFailed(pChannel, loginName, SERVER_ERR_OP_FAILED, datas, true); } PendingLoginMgr::PLInfos* ptinfos = pendingLoginMgr_.find(loginName); if(ptinfos != NULL) { datas = ""; _loginFailed(pChannel, loginName, SERVER_ERR_BUSY, datas, true); return; } ptinfos = new PendingLoginMgr::PLInfos; ptinfos->ctype = ctype; ptinfos->datas = datas; ptinfos->accountName = loginName; ptinfos->password = password; ptinfos->addr = pChannel->addr(); pendingLoginMgr_.add(ptinfos); if(ctype < UNKNOWN_CLIENT_COMPONENT_TYPE || ctype >= CLIENT_TYPE_END) ctype = UNKNOWN_CLIENT_COMPONENT_TYPE; INFO_MSG(fmt::format("Loginapp::login: new client[{0}], loginName={1}, datas={2}.\n", COMPONENT_CLIENT_NAME[ctype], loginName, datas)); pChannel->extra(loginName); // 向dbmgr查询用户合法性 Network::Bundle* pBundle = Network::Bundle::createPoolObject(); (*pBundle).newMessage(DbmgrInterface::onAccountLogin); (*pBundle) << loginName << password; (*pBundle).appendBlob(datas); dbmgrinfos->pChannel->send(pBundle); }
这个函数进行了一系列的检查,确定合法后向dbmgr发送一个登陆请求包“(*pBundle).newMessage(DbmgrInterface::onAccountLogin);
然后在dbmgr.cpp中
//------------------------------------------------------------------------------------- void Dbmgr::onAccountLogin(Network::Channel* pChannel, KBEngine::MemoryStream& s) { std::string loginName, password, datas; s >> loginName >> password; s.readBlob(datas); if(loginName.size() == 0) { ERROR_MSG("Dbmgr::onAccountLogin: loginName is empty.\n"); return; } pInterfacesAccountHandler_->loginAccount(pChannel, loginName, password, datas); }
转到interfaces_handler.cpp中
1 //------------------------------------------------------------------------------------- 2 bool InterfacesHandler_Dbmgr::loginAccount(Network::Channel* pChannel, std::string& loginName, 3 std::string& password, std::string& datas) 4 { 5 std::string dbInterfaceName = Dbmgr::getSingleton().selectAccountDBInterfaceName(loginName); 6 7 thread::ThreadPool* pThreadPool = DBUtil::pThreadPool(dbInterfaceName); 8 if (!pThreadPool) 9 { 10 ERROR_MSG(fmt::format("InterfacesHandler_Dbmgr::loginAccount: not found dbInterface({})!\n",