遊戲服務端之C 網路庫對外介面

2021-07-27 00:00:25 字數 3629 閱讀 2773

大多數的情況下,遊戲的服務端都是在linux下執行,但是linux下做開發c/c++的開發相對來說是比較困難的。所以一般來說,遊戲的服務端都是做成可移植的,這樣方便在windows下做開發。也就是說,服務端既可在windows下執行,也可以在linux下執行。說了這麼多,看似與網路鏈結半毛錢關係都沒有。

其實不是這樣的,就像lua一樣,既可以在windows下呼叫它,也可以在linux呼叫它,關鍵就庫不同。熟悉網路程式設計的都知道,絕大多數的網路api在不同的平台呼叫是不同的。那如何做到可移植呢?其實無論你選擇的網路模型是iocp、select還是epoll。我們使用的時候只關心accept(誰連線到服務端?)、receive(怎樣接收訊息?)和send(怎樣傳送訊息?)。也就是說我們只需要3個介面。send的封裝可以寫進庫的原始檔中,我們只需單例呼叫它就可以了。但是如果accept和receive寫到了原始檔中,那我要怎樣呼叫呢?我要什麼時候呼叫呢?到這裡感覺好像很困難!!

gamesocket.h

#ifndef gamesocket_h  

#define gamesocket_h

#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "luaengine.h"

using namespace std;

#define maxbuf 4096 //4kb may be enough

#define maxepollsize 2048

class gamesocket

~gamesocket();

bool init();

int accept(int userid);

int lose(int userid);

int listen();

int recv(int userid, char msg[maxbuf]);

int send(int userid, char msg, short length);

private:

gamesocket();

int setnonblocking(int socket_fd);

int m_epfd;

int m_listener;

struct sockaddr_in m_their_addr;

struct epoll_event ev;

};

#endif // socket_h

現在要將這個類封裝成靜態庫,而accept和recv是被動觸發的,是根據監聽到的資訊(listen)而觸發的。

gamesocket.cpp就像上面的**乙個,在listen會呼叫下面的**,但是在gamesocket.cpp並沒有對accept和recv的實現,其實這是對外介面的關鍵。

#include "gamesocket.h"  

gamesocket::gamesocket()

gamesocket::~gamesocket()

/* setnonblocking - 设置هڈ¥وں„ن¸؛é‌‍éک»ه،‍و–¹ه¼ڈ

*/

int gamesocket::setnonblocking(int socket_fd)

return 0;

} bool gamesocket::init()

else

/* ه¼€هگ?socket ç›『هگ¬ */

if ((m_listener = socket(pf_inet, sock_stream, 0)) == -1)

else

setnonblocking(m_listener);

bzero(&my_addr, sizeof(my_addr));

my_addr.sin_family = pf_inet;

my_addr.sin_port = htons(port);

my_addr.sin_addr.s_addr = inaddr_any;

if (bind(m_listener, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) == -1)

else

if (listen(m_listener, lisnum) == -1)

else

m_epfd = epoll_create(maxepollsize);

ev.events = epollin | epollet;

ev.data.fd = m_listener;

if (epoll_ctl(m_epfd, epoll_ctl_add, m_listener, &ev) < 0)

else

} int gamesocket::listen()

for (int n = 0; n < nfds; ++n)

if (new_fd < 0)

else

setnonblocking(new_fd);

ev.events = epollin | epollet;

ev.data.fd = new_fd;

if (epoll_ctl(m_epfd, epoll_ctl_add, new_fd, &ev) < 0)

else

curfds++;

} else if (events[n].events & epollin)

else

} }

} int gamesocket::send( int userid, char msg ,short length)

return 1;

}

this->accept(new_fd);

this->recv(events[n].data.fd, recv_buf);

如果在gamesocket.cpp對accept和recv方法實現了,那在呼叫該庫的時候,我們根本不知道怎樣去呼叫accept和recv。所以只有accept和recv在庫外實現,才可能去呼叫這兩個方法。現在將兩個方法的實現寫在了inte***cce.cpp中。

inte***ce.cpp

#include "gamesocket.h"  

int gamesocket::accept(int userid)

int gamesocket::recv(int userid, char msg[maxbuf])

int gamesocket::lose(int userid)

執行結果:

ps:服務端都是訊息響應的,也就是說,當我們獲得訊息(recv)的時候,我們可以對下面的邏輯做多執行緒或者多程序的操作。

遊戲服務端之AOI概述

aoi area of interest 中文就是感興趣區域。通俗一點說,感興趣區域就是玩家在場景實時看到的區域 也就是aoi會隨著英雄的移動改變而改變。一般在遊戲的中,遊戲的世界都是由各種場景組成,場景中有著各種各樣的obj 英雄 怪物 npc和掉落物品等等 當英雄在移動的時候,玩家需要看到其它在...

網路遊戲服務端的多執行緒模型

上周四公司有乙個服務端程式的交流,中間討論到如何有效利用現在伺服器的多核優勢,提高單服的負載。稍有經驗的網路遊戲服務端開發人員,首先會想說把檔案讀寫等操作慢速裝置的操作獨立出來,變成單獨的執行緒,那麼我們可能會把網路io,以及檔案log獨立出來,用單獨的執行緒處理。如果乙個遊戲伺服器,僅開了幾個io...

遊戲服務端框架之客戶端協議組合下發

很多時候,客戶端乙個請求過來,服務端可能需要發多個響應訊息。典型地,當客戶端請求載入登入載入資源完成,服務端需要推送非常多的訊息。功能模組越多,訊息也越多。這個時候,可能就需要對下發的客戶端協議進行優化。個人理解,針對這種情況,比較好的優化方式是整合多個小訊息一起下發。也就是說,對於多個訊息,我們不...