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