日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

MMORPG大型游戏设计与开发(part3 of net)

發(fā)布時(shí)間:2025/3/13 编程问答 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MMORPG大型游戏设计与开发(part3 of net) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

這一部分需要向大家介紹的是服務(wù)器的select以及收發(fā)包的具體流程,從核心代碼功能上分析網(wǎng)絡(luò)交互具體過(guò)程。

  首先大家要看第二部分(part2 of net)的代碼結(jié)構(gòu)圖,因?yàn)樵诮酉聛?lái)的流程過(guò)程中會(huì)用到其中模塊的名稱(chēng),若是不知道大致的功能那么接下來(lái)的解說(shuō)可能就成為天書(shū)了。

  總體流程為:服務(wù)器管理器初始化并創(chuàng)建主套接字連接,進(jìn)入主循環(huán)等待新連接(select),如果有新的連接則將新連接加入連接管理器。不管有沒(méi)有新的連接,循環(huán)會(huì)依次處理連接的異常->輸入流->輸出流->命令處理。其中異常即連接包發(fā)送錯(cuò)誤的處理,輸入流即套接字輸入流中如果大小長(zhǎng)度不為空則重新拼接包,輸出流進(jìn)行包的拼接,并將未發(fā)送的流進(jìn)行發(fā)送,命令處理其實(shí)是對(duì)輸入流的處理,處理(handler)發(fā)送過(guò)來(lái)的包。

  以下詳細(xì)說(shuō)明這幾個(gè)流程從代碼上的實(shí)現(xiàn),以及所在的模塊。

  1、? 服務(wù)器管理器初始化(servermanager)

bool ServerManager::init() {__ENTER_FUNCTIONserversocket_ = new pap_server_common_net::Socket(g_config.billing_info_.port_);Assert(serversocket_);serversocket_->set_nonblocking();socketid_ = serversocket_->getid(); Assert(socketid_ != SOCKET_INVALID); FD_SET(socketid_, &readfds_[kSelectFull]); FD_SET(socketid_, &exceptfds_[kSelectFull]); minfd_ = maxfd_ = socketid_; timeout_[kSelectFull].tv_sec = 0; timeout_[kSelectFull].tv_usec = 0; threadid_ = pap_common_sys::get_current_thread_id(); uint16_t i; for (i = 0; i < OVER_SERVER_MAX; ++i) { serverhash_[i] = ID_INVALID; } return true; __LEAVE_FUNCTION return false; }

  2、? 服務(wù)器管理器進(jìn)入主循環(huán)(servermanager)

?

void ServerManager::loop() {__ENTER_FUNCTIONwhile (isactive()) {bool result = false; try { result = select(); Assert(result); //ERRORPRINTF("select"); result = processexception(); Assert(result); //ERRORPRINTF("processexception"); result = processinput(); Assert(result); //ERRORPRINTF("processinput"); result = processoutput(); Assert(result); //ERRORPRINTF("processoutput"); } catch(...) { } try { result = processcommand(); Assert(result); //ERRORPRINTF("processcommand"); } catch(...) { } try { result = heartbeat(); Assert(result); } catch(...) { } } __LEAVE_FUNCTION } loop

?

  3、? 服務(wù)器線(xiàn)程進(jìn)入select模式

?

bool ServerManager::select() {__ENTER_FUNCTIONtimeout_[kSelectUse].tv_sec = timeout_[kSelectFull].tv_sec;timeout_[kSelectUse].tv_usec = timeout_[kSelectFull].tv_usec;readfds_[kSelectUse] = readfds_[kSelectFull]; writefds_[kSelectUse] = writefds_[kSelectFull]; exceptfds_[kSelectUse] = exceptfds_[kSelectFull]; pap_common_base::util::sleep(100); int32_t result = SOCKET_ERROR; try { result = pap_common_net::socket::Base::select( maxfd_ + 1, &readfds_[kSelectUse], &writefds_[kSelectUse], &exceptfds_[kSelectUse], &timeout_[kSelectUse]); Assert(result != SOCKET_ERROR); } catch(...) { g_log->fast_save_log(kBillingLogFile, "ServerManager::select have error, result: %d", result); } return true; __LEAVE_FUNCTION return false; } select

?

  4、? 服務(wù)器線(xiàn)程進(jìn)行異常處理

?

bool ServerManager::processexception() {__ENTER_FUNCTIONif (SOCKET_INVALID == minfd_ && SOCKET_INVALID == maxfd_)return true; uint16_t connectioncount = billingconnection::Manager::getcount(); billingconnection::Server* serverconnection = NULL; uint16_t i; for (i = 0; i < connectioncount; ++i) { if (ID_INVALID == connectionids_[i]) continue; serverconnection = g_connectionpool->get(connectionids_[i]); Assert(serverconnection); int32_t socketid = serverconnection->getsocket()->getid(); if (socketid_ == socketid) { Assert(false); continue; } if (FD_ISSET(socketid, &exceptfds_[kSelectUse])) { removeconnection(serverconnection); } } return true; __LEAVE_FUNCTION return false; } processexception

?

  5、? 服務(wù)器線(xiàn)程進(jìn)行輸入流處理

?

bool ServerManager::processinput() {__ENTER_FUNCTIONif (SOCKET_INVALID == minfd_ && SOCKET_INVALID == maxfd_)return true; //no connection uint16_t i; if (FD_ISSET(socketid_, &readfds_[kSelectUse])) { for (i = 0; i < kOneStepAccept; ++i) { if (!accept_newconnection()) break; } } uint16_t connectioncount = billingconnection::Manager::getcount(); for (i = 0; i < connectioncount; ++i) { if (ID_INVALID == connectionids_[i]) continue; billingconnection::Server* serverconnection = NULL; serverconnection = g_connectionpool->get(connectionids_[i]); Assert(serverconnection); int32_t socketid = serverconnection->getsocket()->getid(); if (socketid_ == socketid) continue; if (FD_ISSET(socketid, &readfds_[kSelectUse])) { //read information if (serverconnection->getsocket()->iserror()) { removeconnection(serverconnection); } else { try { if (!serverconnection->processinput()) removeconnection(serverconnection); } catch(...) { removeconnection(serverconnection); } } } } return true; __LEAVE_FUNCTION return false; } processinput

?

  6、? 服務(wù)器線(xiàn)程進(jìn)行輸出流處理

?

bool ServerManager::processoutput() {__ENTER_FUNCTIONif (SOCKET_INVALID == maxfd_&& SOCKET_INVALID == minfd_)return false; uint16_t i; uint16_t connectioncount = billingconnection::Manager::getcount(); for (i = 0; i < connectioncount; ++i) { if (ID_INVALID == connectionids_[i]) continue; billingconnection::Server* serverconnection = NULL; serverconnection = g_connectionpool->get(connectionids_[i]); Assert(serverconnection); int32_t socketid = serverconnection->getsocket()->getid(); if (socketid_ == socketid) continue; if (FD_ISSET(socketid, &writefds_[kSelectUse])) { if (serverconnection->getsocket()->iserror()) { removeconnection(serverconnection); } else { try { if (!serverconnection->processoutput()) removeconnection(serverconnection); } catch(...) { removeconnection(serverconnection); } } } } return true; __LEAVE_FUNCTION return false; } processoutput

?

  7、? 服務(wù)器線(xiàn)程進(jìn)行命令處理

bool ServerManager::processcommand() {__ENTER_FUNCTIONif (SOCKET_INVALID == maxfd_&& SOCKET_INVALID == minfd_)return false; uint16_t i; uint16_t connectioncount = billingconnection::Manager::getcount(); for (i = 0; i < connectioncount; ++i) { if (ID_INVALID == connectionids_[i]) continue; billingconnection::Server* serverconnection = NULL; serverconnection = g_connectionpool->get(connectionids_[i]); //serverconnection = &billing_serverconnection_; Assert(serverconnection); int32_t socketid = serverconnection->getsocket()->getid(); if (socketid_ == socketid) continue; if (serverconnection->getsocket()->iserror()) { removeconnection(serverconnection); } else { //connection is ok try { if (!serverconnection->processcommand(false)) removeconnection(serverconnection); } catch(...) { removeconnection(serverconnection); } } } return true; __LEAVE_FUNCTION return false; } processcommand

?

  下一部分,我將講解在網(wǎng)絡(luò)部分一些重要的代碼塊。

轉(zhuǎn)載于:https://www.cnblogs.com/liuzhi/p/4084565.html

總結(jié)

以上是生活随笔為你收集整理的MMORPG大型游戏设计与开发(part3 of net)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。