📄 csdn_文档中心_myicq情景分析.htm
字号:
(IcqWindow *) *it;<BR> if
(win->type == type && (!qid || win->qid == *qid) </P>
<P
style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">
&& (seq == 0 || win->seq ==
seq))<BR>
return win;<BR>
}<BR> return NULL;<BR>}</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">接上程序<BR>293 if (win)
{<BR>294 ((CRegWizard *)
win)->onConnect(success);<BR>295
return;<BR>296 }<BR>........}</P>
<P
style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">本情景中WIN_REG_WIZARD存在所以进入((CRegWizard
*) win)->onConnect(success);</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">void onConnect(bool
success) {<BR>
finishDlg.onConnect(success);<BR>}</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">void
CRegFinishDlg::onConnect(bool success)<BR>{<BR>148
if (success) {<BR>149
CRegWizard *<A name=wiz>wiz</A> = (CRegWizard *)
GetParent();<BR>150 if
(wiz->modeDlg.m_mode ==
0)<BR>151
wiz->seq =
getUdpSession()->regNewUIN(wiz->basicDlg.m_passwd);<BR>152
else {<BR>153
icqLink->myInfo.qid.uin =
wiz->modeDlg.m_uin;<BR>
wiz->seq =
getUdpSession()->login(wiz->modeDlg.m_passwd,STATUS_OFFLINE);<BR>155
}<BR>156 }
else<BR>157
onTimeout();<BR>}</P>
<P
style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">modeDlg.m_mode如选中新申请一个QQ号则为0,选中已有QQ号为1,本情景为0所以到151行</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">uint16
UdpSession::regNewUIN(const char *passwd)<BR>{<BR> <A
href="file:///D:/cldata/study/user_register.htm#regNewUIN_001">001</A>
initSession();<BR> <A
href="file:///D:/cldata/study/user_register.htm#regNewUIN_002">002</A>
UdpOutPacket *out = createPacket(UDP_NEW_UIN);<BR> <A
href="file:///D:/cldata/study/user_register.htm#regNewUIN_003">003</A>
*out << passwd;<BR> <A
href="file:///D:/cldata/study/user_register.htm#regNewUIN_004">004</A>
return sendPacket(out);<BR>}</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px"><A
name=regNewUIN_001></A>先看001 regNewUIN主要功能是注册一个新ID,</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">void
UdpSession::initSession()<BR>{<BR>161 sid = (rand() &
0x7fffffff) + 1; //将sid初值赋值为随机数</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">162 sendSeq = (rand()
& 0x3fff); </P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">163 retryKeepAlive =
0;<BR>164 sessionCount = 0;<BR>165<BR>166 memset(window, 0,
sizeof(window));<BR>167<BR>168
clearSendQueue();
//清空发送队列<BR>}</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px"><A
name=regNewUIN_002></A>再看002</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">(1) UdpOutPacket
*UdpSession::createPacket(uint16 cmd)<BR>{<BR>
UdpOutPacket *p = new UdpOutPacket;<BR> p->cmd
= cmd;<BR> p->seq =
++sendSeq;<BR> createPacket(*p, cmd,
sendSeq);<BR> return p;<BR>}</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">(2) void
UdpSession::createPacket(UdpOutPacket &out, uint16 cmd, uint16
seq)<BR>{<BR> out << (uint16) MYICQ_UDP_VER
<< (uint32) 0;<BR> out <<
icqLink->myInfo.qid.uin << sid << cmd <<
seq;<BR> out << (uint16) 0; // Checkcode
will be calculated later<BR>}</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">(3) OutPacket
&IcqOutPacket::operator <<(uint16
w)<BR>{<BR> if (cursor <= data +
MAX_PACKET_SIZE - sizeof(w))
{<BR> *(uint16 *) cursor =
htons(w);<BR> cursor +=
sizeof(w); }<BR> return (*this);<BR>}</P>
<P
style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">继承关系:UdpOutPacket->IcqOutPacket->OutPacket->Packet</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">cmd =
UDP_NEW_UIN,cusor和data的初始化是在哪里做的呢?看代码:</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">class IcqOutPacket :
public OutPacket {<BR> public:<BR>
IcqOutPacket() {<BR>
cursor = data; }</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px"> ...<BR>
...</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">
protected:<BR> char
data[MAX_PACKET_SIZE];<BR> char *cursor;};</P>
<P
style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">(3)是第一句主要是为了判断cursor的长度+sizeof(w)是否超过了MAX_PACKET_SIZE如没超过就将w转换为网络字节后赋值给cursor当前的地址</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">
然后移动cursor的指针+w</P>
<P
style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">(2)中的后几句都是将数据赋给data.
也就是说将MYICQ_UDP_VER -0- icqLink->myInfo.qid.uin -sid - cmd
-seq-0连起来赋给data.</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px"> 其中
MYICQ_UPD_VER =
1,icqLink->myInfo.qid.uin=申请一个QQ号则为0,选中已有QQ号为1,sid=随机数,cmd
=UDP_NEW_UIN,seq=随机数</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px"><A
name=regNewUIN_003></A>再看003: *out << passwd;
再给data加上passwd;</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px"><A
name=regNewUIN_004></A>最后004: sendPacket(out) 看看</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px"> </P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">uint16
UdpSession::sendPacket(UdpOutPacket *p)<BR>{<BR>
// Packet must be encrypted before sending to
server<BR>1 if (p->cmd != UDP_NEW_UIN
&& p->cmd !=
UDP_LOGIN)<BR>2
p->encrypt();<BR>3 p->attempts =
0;<BR>4 p->expire = time(NULL) +
SEND_TIMEOUT;<BR>5
sendDirect(p);<BR>6
sendQueue.push_back(p);<BR>7 return
sendSeq;<BR>}</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">1-2
如果cmd不等于注册新ID和登陆的话就加密.</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">expire是定义超时时间,
attempts 企图尝试的次数,</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">到达5</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">void
UdpSession::sendDirect(UdpOutPacket *out)<BR>{<BR>
if
(icqLink->isProxyType(PROXY_HTTP))<BR>
sendDirect(out, httpProxy.sock);<BR>
else<BR> sendDirect(out,
sock);<BR>}</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">是否使用了代理服务器如没使用就用int
sock,它在UpdSession的构造函数中被初始化为 </P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px"><A
name=SocketListener></A></P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">sock =
IcqSocket::createSocket(SOCK_DGRAM, this);</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px"><A
name=CMySocket></A></P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">int
IcqSocket::createSocket(int type, SocketListener
*l)<BR>{<BR> CMySocket *pSocket = new
CMySocket(l);<BR> pSocket->Create(0, type,
FD_READ | FD_CONNECT | FD_CLOSE);<BR> return
addSocket(pSocket);<BR>}</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">(1)
createSocket第一行在堆上创建了一个CMySocket 它继承于CAsyncSocket类,看它的构造函数</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">
CMySocket::CMySocket(SocketListener
*l)<BR> {
listener = l;}<BR>
SocketListener是一个纯虚函数,它是UdpSession的父类,它改写了SocketListener的onReceive的虚函数。</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">(2)
createSocket第二行是Create函数,以SOCK_DGRAM(TCP协议)创建了一个Socket对象</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">(3) 看看第三行的代码</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">
inline int addSocket(CAsyncSocket *pSocket)<BR>
{<BR> int sock =
*pSocket;<BR>
sockHash.SetAt(sock,
pSocket);<BR> return
sock;<BR> }</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">
static CMap<int, int, CAsyncSocket*, CAsyncSocket*>
sockHash;</P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px"> </P>
<P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">void
UdpSession::sendDirect(UdpOutPacket *out, int
s)<BR>{<BR>203 char buf[MAX_PACKET_SIZE +
256];<BR>204 char *p = buf;<BR>205 int n =
out->getSize();
<BR>206<BR>207 IcqOption &options =
icqLink->options;<BR>208<BR>209 if
(options.flags.test(UF_USE_PROXY))
{<BR>210 switch
(options.proxyType)
{<BR>211 case
PROXY_HTTP:<BR>212
*(uint16 *) p =
htons(n);<BR>213
p +=
sizeof(uint16);<BR>214
break;<BR>215<BR>216
case
PROXY_SOCKS:<BR>217
*(uint16 *) p =
0;<BR>218
p +=
sizeof(uint16);<BR>219
*p++ =
0;<BR>220
if (options.proxy[PROXY_SOCKS].resolve)
{<BR>221
//
IPv4<BR>222
*p++ =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -