📄 csdn_文档中心_myicq情景分析.htm
字号:
1;<BR>223
*(uint32 *) p =
destIP;<BR>224
p +=
sizeof(uint32);<BR>225
} else
{<BR>226
// Domain
name<BR>227
*p++ =
3;<BR>228
string &domain =
icqLink->myInfo.qid.domain;<BR>229
uint8 len =
domain.length();<BR>230
*p++ =
len;<BR>231
memcpy(p, domain.c_str(),
len);<BR>232
p +=
len;<BR>233
}<BR>234
*(uint16 *) p =
htons(options.port);<BR>235
p +=
sizeof(uint16);<BR>236
break;<BR>237
}<BR>238 }<BR>239 memcpy(p,
out->getData(), n);<BR>240 p += n;<BR>241
send(s, buf, p - buf, 0);<BR> }</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px"><A name=main></A></P>
<P
style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">此函数功能主要是通过send()发送数据(updsesson::data)给服务器,本情景也就是发用户填写的信息.</P>
<P
style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">从此将进入服务器代码直到服务器返回为此。看服务器代码:</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">此函数在main.cpp中</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">int main(int argc,
char *argv[])<BR>{<BR>66 WSADATA
wsaData;<BR>67 WORD version = MAKEWORD(2,
2);<BR>68 if (WSAStartup(version,
&wsaData) !=
0)<BR>69 return
1;<BR>70<BR>71 initArgs(argc,
argv);<BR>72<BR>73 #ifndef _DEBUG<BR>74 if
(!startService())<BR>75 #endif<BR>76
{<BR>77 // We are not in service
mode<BR>78 if
(myicqStart())
{<BR>79
handlePacket();<BR>80
myicqDestroy();<BR>81
}<BR>82
}<BR>83<BR>84
WSACleanup();<BR>85 return 0;<BR>}</P>
<P
style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">66行到70行初始化winsock,版本为2.2。71行的initArgs(argc,argv)处理参数主要是如果是windows的话将myicq加入到服务中,以后系统启动时自动运行。到78行我们看myicqStart的代码(main.cpp),main()->myicqStart()</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">bool
myicqStart()<BR>{<BR>45 if
(!myicqInit())<BR>46
return
false;<BR>进入myicqInit(myicq.cpp)中,main()->myicqStart()->myicqInit()</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">bool
myicqInit()<BR>{<BR>187
srand(time(&curTime));<BR>188<BR>189
parseProfile(CONFIG_FILE,
parseConfig);<BR>190<BR>191
Log::open(_ops.logFile.c_str(),
_ops.logLevel);<BR>192<BR>193
loadPlugins();<BR>194<BR>195 // Initialize
database subsystem<BR>196 if
(!DBManager::init(_ops.dbInfo))
{<BR>197 LOG(1)
("Cannot connect to mysql
master\n");<BR>198
return false;<BR>199
}<BR>200 for (int i = 0; i < NR_DB_QUERY;
++i) {<BR>201 if
(!dbQuery[i].create(_ops.dbInfo))
{<BR>202
LOG(1) ("Cannot connect to mysql
slave\n");<BR>203
return false;<BR>204
}<BR>205
}<BR>206<BR>207 if
(!UdpSession::init())<BR>208
return false;<BR>209<BR>210 if
(_ops.enableS2S)
{<BR>211 if
(!Server::init())<BR>212
return
false;<BR>213<BR>214
LOG(1) ("domain name is %s\n",
_ops.domain.c_str());<BR>215
}<BR>216<BR>217 LOG(1) ("myicqd is now
started.\n");<BR>218 return true;<BR>}</P>
<P
style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">189行的parseProfile是函数主要功能是从CONFIG_FILE指定的文件中取各各节的内容存入OPTIONS
_ops这个全局结构中.</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">struct OPTIONS
{<BR> // network<BR> uint32
myicqIP;<BR> uint16
myicqPort;<BR> // log<BR> int
logLevel;<BR> string
logFile;<BR> // mysql<BR>
DB_INFO dbInfo;<BR> int
enableRegister;<BR> int
enableS2S;<BR> // server<BR>
string domain;<BR> string
desc;<BR> // plugins<BR> string
pluginDir;<BR>};</P>
<P
style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">191打开日志文件,193加载插件模块。196-199通过调用mysql_init(mysql提供)并用mysql_real_connect连接;初始化mysql赋给mysqlWrite,参数是_ops.dbInfo.,200-205也是调用mysql_init来初始化mysql_real_connect连接;static
DBManager dbQuery[NR_DB_QUERY];结构中的MYICQ*
mysqlRead;,207-208初始化UPD服务UpdSession::init()(updsession.cpp)</P>
<P
style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">main()->myicqStart()->myicqInit()->UpdSession::init()</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">bool
UdpSession::init()<BR>{<BR>696 sockaddr_in
addr;<BR>697<BR>698 qidAdmin.uin =
ADMIN_UIN;<BR>699 qidAdmin.domain =
emptyStr;<BR>700<BR>701 sock =
socket(AF_INET, SOCK_DGRAM, 0);<BR>702 if
(sock < 0)
{<BR>703 LOG(1)
("socket()
failed\n");<BR>704
goto failed;<BR>705
}<BR>706<BR>707 memset(&addr, 0,
sizeof(addr));<BR>708 addr.sin_family =
AF_INET;<BR>709 addr.sin_addr.s_addr =
_ops.myicqIP;<BR>710 addr.sin_port =
_ops.myicqPort;<BR>711 if (bind(sock,
(sockaddr *) &addr, sizeof(addr)) < 0)
{<BR>712 LOG(1)
("bind(): Can not bind on
%s:%d\n",<BR>713
inet_ntoa(addr.sin_addr),
ntohs(_ops.myicqPort));<BR>714
goto failed;<BR>715
}<BR>716<BR>717
desinit(0);<BR>718 return
true;<BR>719<BR>720
failed:<BR>721 if (sock >=
0)<BR>722
close(sock);<BR>723 return false;<BR>}</P>
<P
style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">此函数就是对socket的一些初始化工作socket初始化流程
socket() --- bind() ---
listen()注:此函数中还没有listen()用的是(无连接的)UDP协议</P>
<P
style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">Server::init()主要是初始化(面向连接的)TCP协议,然后返回到myicqStart中看代码:</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px"><A
name=Thread></A></P>
<P
style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">48
DWORD id;<BR>49 int
i;<BR>50<BR>51 // Creating
threads...<BR>52 CreateThread(NULL, 0,
pulseThread, NULL, 0, &id);<BR>53<BR>54
// DNS<BR>55 CreateThread(NULL, 0,
dnsThread, NULL, 0, &id);<BR>56<BR>57
CreateThread(NULL, 0, dbUpdateThread, NULL, 0,
&id);<BR>58 for (i = 0; i <
NR_DB_QUERY;
++i)<BR>59
CreateThread(NULL, 0, dbQueryThread, (LPVOID) i, 0,
&id);<BR>60<BR>61 return
true;<BR>}<BR>建立了几个线程回调函数分别是pulseThread, dnsThread, dbUpdateThread,
dbQueryThread;</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">static DWORD WINAPI
pulseThread(LPVOID)<BR>{<BR>
pulse();<BR> return 0;<BR>}</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">void
pulse()<BR>{<BR> for (;;)
{<BR> time((time_t *)
&curTime);<BR>
sleep(1);<BR> }<BR>}</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">static DWORD WINAPI
dnsThread(LPVOID)<BR>{ <BR>
handleDNS();<BR> return 0;<BR>}</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">void
handleDNS()<BR>{<BR>
DNSManager::process();<BR>}</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">static DWORD WINAPI
dbUpdateThread(LPVOID)<BR>{<BR>
handleDBUpdate();<BR> return 0;<BR>}</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">void
handleDBUpdate()<BR>{<BR>
DBManager::processUpdate();<BR>}</P>
<P
style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">先继续向下看吧!回到main中还剩以下几行</P>
<P
style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">79
handlePacket();<BR>80
myicqDestroy();<BR>81
}<BR>82
}<BR>83<BR>84
WSACleanup();<BR>85 return 0;</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">}</P>
<P
style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">最重要的是handlePacket(),看代码:</P>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -