myicq1.0a1服务器代码分析(三)服务器集群
顾剑辉(Solarsoft)
服务器集群其实是服务器之间建立联系,并维护这样的联系,如:玩联众时,你会看到很多服务器,那它们是怎样共同工作的呢!分析如下:
服务器与服务器之间一般用TCP进行连接,并在每个服务器中都建立这个表,表中包括相应的信息,如服务器IP,port,包括游戏的每个服务器在线人员人数,等等.当你进入别的游戏主机时,其实是一个退出当前服务器,登入其他服务器的过程,相应的在线数据,服务器之间会传送好的.
接下去,我们一起来看一下,myicq是怎样做到集群的.
class ServerHash {
public:
void put(Server *s) {
int i = hashfn(s->ip);
hash[i].addHead(&s->hashItem);
}
Server *get(uint32 ip);
private:
int hashfn(uint32 ip) {
return (ip & (SERVER_HASH_SIZE - 1));
}
ListHead hash[SERVER_HASH_SIZE];
};
Server *ServerHash::get(uint32 ip)
{
int i = hashfn(ip);
ListHead *head = &hash[i];
ListHead *pos;
LIST_FOR_EACH(pos, head) {
Server *s = LIST_ENTRY(pos, Server, hashItem);
if (s->ip == ip)
return s;
}
return NULL;
}
ListHead Server::serverList;
static ServerHash serverHash;
这里其实是服务器在线列表的hash表管理,这个hash管理不清楚的,你可以看一下我的文章(一).
再来看一下,用于服务器连接的socket类,其中RefObject是起个计数器的作用.
class Server : public RefObject {
public:
Server();
virtual ~Server();
void onDnsResolved(uint32 ip);
void onConnect();
void onReceive();
void onClose();
bool connect(uint32 ip, uint16 port);
RemoteSession *getSession(uint32 uin);
void sendUserOnline(Session *s);
void sendUserOffline(uint32 uin);
void sendUserStatus(uint32 uin, uint32 status);
void sendMessage(uint8 type, uint32 dst, uint32 src, ICQ_STR &text);
void addFriend(uint16 seq, uint32 dst, uint32 src);
void delFriend(uint32 dst, uint32 src);
void updateContact(uint16 seq, uint32 dst, uint32 src);
void searchRandom(uint16 seq, uint32 src);
void searchUIN(uint16 seq, uint32 dst, uint32 src);
void addFriendReply(uint16 seq, uint32 dst, uint32 src, uint8 auth);
void updateContactReply(uint16 seq, uint32 src, uint8 *data, int n);
void searchUINReply(uint16 seq, uint32 src, uint8 *data, int n);
static bool init();
static void destroy();
static Server *getServer(const char *name);
static Server *createServer(const char *name);
static RemoteSession *getSession(QID &qid);
static int generateFds(fd_set &readfds, fd_set &writefds);
static void examineFds(fd_set &readfds, fd_set &writefds);
static ListHead serverList;
char domainName[MAX_DOMAIN_NAME + 1];
char descName[MAX_DESC_NAME + 1];
ICQ_STR domain;
ICQ_STR desc;
uint32 ip;
int sock;
int status;
time_t expire;
uint32 sessionCount;
bool isAccepted;
ListHead listItem;
ListHead hashItem;
private:
bool setDomainAndDesc(ICQ_STR &name, ICQ_STR &des);
RemoteSession *createSession(uint32 uin);
void notify(uint32 uin, DB_CALLBACK cb);
void createPacket(TcpOutPacket &out, uint16 cmd);
TcpOutPacket *createPacket(uint16 cmd);
void sendPacket(TcpOutPacket *out);
void sendPendingPacket(int s);
void onPacketReceived(TcpInPacket &in);
void onHello(TcpInPacket &in);
void onSendMessage(TcpInPacket &in);
void onAddFriend(TcpInPacket &in);
void onDelFriend(TcpInPacket &in);
void onUserOnline(TcpInPacket &in);
void onUserOffline(TcpInPacket &in);
void onUserStatus(TcpInPacket &in);
void onUpdateContact(TcpInPacket &in);
void onSearchRandom(TcpInPacket &in);
void onSearchUIN(TcpInPacket&in);
void onHelloReply(TcpInPacket &in);
void onAddFriendReply(TcpInPacket &in);
void onUpdateContactReply(TcpInPacket &in);
void onSearchRandomReply(TcpInPacket &in);
void onSearchUINReply(TcpInPacket &in);
char buf[TCP_PACKET_SIZE];
int bufSize;
ListHead uinHash[UIN_HASH_SIZE];
ListHead sessionList;
ListHead sendQueue;
DECLARE_SLAB(Server)
};
上面的程序,我不做太多解释,我想大家也应该看得懂,如有疑问可以发表看法,来讨论一下.
本文地址:http://com.8s8s.com/it/it1330.htm