myicq情景源代码分析.docx
- 文档编号:29615027
- 上传时间:2023-07-25
- 格式:DOCX
- 页数:33
- 大小:29.63KB
myicq情景源代码分析.docx
《myicq情景源代码分析.docx》由会员分享,可在线阅读,更多相关《myicq情景源代码分析.docx(33页珍藏版)》请在冰豆网上搜索。
myicq情景源代码分析
选择自CSDNclzzcl的Blog
1.第一个情景:
用户注册
这个情景主要用到的数据结构:
(1)IcqUser
让我们先来看IcqUser的代码,
classIcqUser:
publicIcqInfo{
public:
IcqUser();
voidload(DBInStream&in);
voidsave(DBOutStream&out);
stringpasswd;
uint8auth;
};
classIcqInfo:
publicContactInfo,publicDBSerialize{
public:
IcqInfo();
virtual~IcqInfo(){}
voidsave(DBOutStream&out);
voidload(DBInStream&in);
};
classContactInfo{
public:
QIDqid;
stringnick;
uint8face;
uint8gender;
uint8age;
stringcountry;
stringprovince;
stringcity;
stringemail;
stringaddress;
stringzipcode;
stringtel;
stringname;
uint8blood;
stringcollege;
stringprofession;
stringhomepage;
stringintro;
uint32status;
};
classDBSerialize{
public:
virtualvoidsave(DBOutStream&out)=0;
virtualvoidload(DBInStream&in)=0;
};
很明显可以看出它是用来存储人员基本信息的数据结构,它有两个方法save和load,我们来看看它们的代码,
可以想出它是用来将数据成员存入数据库和从数据库读出.DBSerialize是一个抽象类。
voidIcqUser:
:
load(DBInStream&in)
{
IcqInfo:
:
load(in);
in>>passwd>>auth;
}
voidIcqUser:
:
save(DBOutStream&out)
{
IcqInfo:
:
save(out);
out< } voidIcqInfo: : load(DBInStream&in) { in>>face>>nick>>age>>gender>>country>>province>>city; in>>email>>address>>zipcode>>tel; in>>name>>blood>>college>>profession>>homepage>>intro; } voidIcqInfo: : save(DBOutStream&out) { out< out< out< } /* *Utilityclassthatreadsfromorwritestoadatablock */ classDBOutStream{ public: DBOutStream(){ cursor=data; } char*getData(){ returndata; } intgetSize(){ return(cursor-data); } DBOutStream&operator<<(uint8b); DBOutStream&operator<<(uint16w); DBOutStream&operator<<(uint32dw); DBOutStream&operator<<(constchar*str); DBOutStream&operator<<(StrList&strList); DBOutStream&operator<<(conststring&str){ returnoperator<<(str.c_str()); } DBOutStream&operator<<(constQID&qid){ return(*this< } private: chardata[MAX_BLOCK_SIZE]; char*cursor; }; classDBInStream{ public: DBInStream(void*d,intn){ cursor=data=(char*)d; datalen=n; } DBInStream&operator>>(uint8&b); DBInStream&operator>>(uint16&w); DBInStream&operator>>(uint32&dw); DBInStream&operator>>(string&str); DBInStream&operator>>(StrList&strList); DBInStream&operator>>(QID&qid){ return(*this>>qid.uin>>qid.domain); } private: char*data; char*cursor; intdatalen; }; (2)IcqOption classIcqOption: publicDBSerialize{ public: IcqOption(); virtual~IcqOption(); voidload(DBInStream&in); voidsave(DBOutStream&out); voidplaySound(intsound,IcqContact*c=NULL); bitset uint32hotKey; stringsoundFiles[NR_SOUNDS]; stringhost; uint16port; stringautoReplyText; stringquickReplyText; uint32autoStatus; uint32autoStatusTime; stringskin; //Proxystuff uint8proxyType; ProxyInfoproxy[NR_PROXY_TYPES]; private: boolplaySound(constchar*file); }; 存储各种选项 在这个情景里,我们假定用户已经点击网络设置那一页的下一步按钮。 进入以下代码中: BOOLCRegFinishDlg: : OnSetActive() { 206CRegWizard*wiz=(CRegWizard*)GetParent(); 207wiz->getData(&icqLink->myInfo,&icqLink->options); 首先206行取到上个窗口的指针,就是属性表的指针,进而调用它的函数getData。 进入代码: CRegFinishDlg: : OnSetActive()-->CRegWizard: : getData() 54voidCRegWizard: : getData(IcqUser*info,IcqOption*options) 55{ 56if(modeDlg.m_mode==0) 57info->qid=qid; 58else{ 59info->qid.uin=modeDlg.m_uin; 60info->qid.domain=finishDlg.domain; 61} 62 63info->face=basicDlg.m_pic; 64info->age=basicDlg.m_age; 65info->nick=basicDlg.m_nick; 66info->gender=basicDlg.m_gender; 67info->country=basicDlg.m_country; 68info->province=basicDlg.m_province; 69info->city=basicDlg.m_city; 70 71info->email=commDlg.m_email; 72info->address=commDlg.m_address; 73info->zipcode=commDlg.m_zipcode; 74info->tel=commDlg.m_tel; 75 76info->name=miscDlg.m_name; 77info->blood=miscDlg.m_blood; 78info->college=miscDlg.m_college; 79info->profession=miscDlg.m_profession; 80info->homepage=miscDlg.m_homepage; 81info->intro=miscDlg.m_intro; 82 83info->passwd=(modeDlg.m_mode==0? basicDlg.m_passwd: modeDlg.m_passwd); 84 85if(options){ 86options->host=networkDlg.m_host; 87options->port=networkDlg.m_port; 88options->flags.set(UF_USE_PROXY,networkDlg.m_useProxy); 89options->proxyType=networkDlg.m_proxyType; 90for(inti=0;i 91options->proxy[i]=networkDlg.proxyInfo[i]; 92} 93} 此方法传入两个结构IcqUser和IcqOption以上有说明 第56行到第61行,主要给qid赋值,modeDlg.m_mode如选中新申请一个QQ号则为0,选中已有QQ号为1,本情景为0,也就是将info->qid=qid;qid是IcqWindow的一个公有变量QIDqid classQID{ public: QID(){ uin=0; } booloperator==(constQID&qid){ return(uin==qid.uin&&! strcasecmp(domain.c_str(),qid.domain.c_str())); } boolisAdmin(){ return(uin==ADMIN_UIN&&domain.empty()); } char*toString(); boolparse(constchar*qid); uint32uin; stringdomain; }; 剩下的代码就是根据这几个对话框所添入的东东给全局变量icqLink中的IcqUser和IcqOption的各成员变量赋值. 回到RegFinishDlg: : OnSetActive()中第208行开始, 208wiz->qid.uin=0; 209 210CStringstr; 211str.LoadString(IDS_PLEASE_WAIT); 212SetDlgItemText(IDC_STATUS,str); 213str.LoadString(IDS_REG_REGISTERING); 214SetDlgItemText(IDC_STATUS_DETAIL,str); 215wiz->SetWizardButtons(PSWIZB_DISABLEDFINISH); 216 217m_faceLabel.start(); 218 219resolveHost(); 220 221returnCPropertyPage: : OnSetActive(); } 这行将MyIcq号赋为0,211-218设置一些状态,219进入CRegFinishDlg: : resolveHost() voidCRegFinishDlg: : resolveHost() { 172 CRegWizard*wiz=(CRegWizard*)GetParent(); 173 constchar*host=wiz->networkDlg.m_host; 174 175 if(wiz->networkDlg.m_useProxy&&! wiz->networkDlg.m_proxyResolve) 176 getUdpSession()->connect(host,wiz->networkDlg.m_port); 177 else{ 178 structin_addraddr; 179 addr.s_addr=inet_addr(host);//将x.x.x.x转换为无符号整数给addr.s_addr 180 if(addr.s_addr! =INADDR_NONE) 181 onHostFound(addr); 182 else 183 ((CIcqDlg*)AfxGetMainWnd())->getHostByName(host); } } 175行看出在网络设置对话框中有没有选使用代理服务器,本情景中没选到178行将用户选定的地址作为参数传给onHostFound(addr);进入onHostFound voidCRegFinishDlg: : onHostFound(structin_addr&addr) { 163 if(addr.s_addr! =INADDR_NONE){ 164 CRegWizard*wiz=(CRegWizard*)GetParent(); 165 getUdpSession()->connect(inet_ntoa(addr),wiz->networkDlg.m_port); 166 }else 167 onTimeout(); } 在165行调用函数getUpdSession()->connect传入参数是用户输入的地址和端口。 inlineUdpSession*getUdpSession() { returnicqLink->udpSession; } voidUdpSession: : connect(constchar*host,uint16port) { 090 IcqOption&options=icqLink->options; 091 092 //Connectusingproxy 093 if(options.flags.test(UF_USE_PROXY)){ 094 if(options.proxyType==PROXY_SOCKS) 095 socksProxy.start(options.proxy[PROXY_SOCKS],sock); 096 elseif(options.proxyType==PROXY_HTTP) 097 httpProxy.start(host,options.proxy[PROXY_HTTP]); } 099 else{ //notuseproxy 100 sockaddr_inaddr; 101 socklen_tlen=sizeof(addr); 103 memset(&addr,0,sizeof(addr)); 104 addr.sin_family=AF_INET; 105 addr.sin_port=htons(port); 106 addr.sin_addr.s_addr=inet_addr(host); 107 : : connect(sock,(sockaddr*)&addr,len); 109 getsockname(sock,(sockaddr*)&addr,&len); 110 realIP=ntohl(addr.sin_addr.s_addr); 112 icqLink->onConnect(true); } } 首先判断有没有用proxy本情景中没有用所以到100行调用几个SOCKET函数连接传入的服务器及端口,将真实IP存放在realIP中,然后调用icqLink->onConnect(true);这个函数是一个虚函数, CicqDlg类改写了它,所以程序进入CIcqDlg: : onConnect voidCIcqDlg: : onConnect(boolsuccess) { 292IcqWindow*win=findWindow(WIN_REG_WIZARD); 进入findWindow IcqWindow*IcqLink: : findWindow(inttype,QID*qid,uint32seq) { PtrList: : iteratorit; for(it=windowList.begin();it! =windowList.end();++it){ IcqWindow*win=(IcqWindow*)*it; if(win->type==type&&(! qid||win->qid==*qid) &&(seq==0||win->seq==seq)) returnwin; } returnNULL; } 接上程序 293if(win){ 294 ((CRegWizard*)win)->onConnect(success); 295 return; 296} ........} 本情景中WIN_REG_WIZARD存在所以进入((CRegWizard*)win)->onConnect(success); voidonConnect(boolsuccess){ finishDlg.onConnect(success); } voidCRegFinishDlg: : onConnect(boolsuccess) { 148 if(success){ 149 CRegWizard*wiz=(CRegWizard*)GetParent(); 150 if(wiz->modeDlg.m_mode==0) 151 wiz->seq=getUdpSession()->regNewUIN(wiz->basicDlg.m_passwd); 152 else{ 153 icqLink->myInfo.qid.uin=wiz->modeDlg.m_uin; wiz->seq=getUdpSession()->login(wiz->modeDlg.m_passwd,STATUS_OFFLINE); 155 } 156 }else 157 onTimeout(); } modeDlg.m_mode如选中新申请一个QQ号则为0,选中已有QQ号为1,本情景为0所以到151行 uint16UdpSession: : regNewUIN(constchar*passwd) { 001 initSession(); 002 UdpOutPacket*out=createPacket(UDP_NEW_UIN); 003 *out< 004 returnsendPacket(out); } 先看001regNewUIN主要功能是注册一个新ID, voidUdpSession: : initSession() { 161sid=(rand()&0x7fffffff)+1; //将sid初值赋值为随机数 162sendSeq=(rand()&0x3fff); 163retryKeepAlive=0; 164sessionCount=0; 165 166memset(window,0,sizeof(window)); 167 168clearSendQueue(); //清空发送队列 } 再看002 (1)UdpOutPacket*UdpSession: : createPacket(uint16cmd) { UdpOutPacket*p=newUdpOutPacket; p->cmd=cmd; p->seq=++sendSeq; createPacket(*p,cmd,sendSeq); returnp; } (2)voidUdpSession: : createPacket(UdpOutPacket&out,uint16cmd,uint16seq) { out<<(
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- myicq 情景 源代码 分析