Reprint Please specify source:http://blog.csdn.net/mxway/article/details/44889871
This paper is based on the v2.06 of the source code of Flying Pigeon biography.
1. Add a file to send
The file is sent in the Send dialog box, where you first find the shortcut menu for the Send dialog box.
The menu ID for File transfer is Menu_fileadd, and the corresponding command handling event is in the Evcommand function in Senddlg.cpp
BOOLTsenddlg::evcommand (Word wnotifycode, Word wID, LPARAM hwndctl) {Switch(WID) { CaseMenu_fileadd: {CharBuf[max_path] ="";if(Tsharedlg::fileadddlg ( This, Sharemng, Shareinfo? Shareinfo: (Shareinfo = Sharemng->createshare (Packetno)), CFG) {Setfilebutton ( This, File_button, Shareinfo); Evsize (size_restored,0,0); } } Break; }}BOOLTsharedlg::fileadddlg (Tdlg *dlg, sharemng *sharemng, Shareinfo *shareinfo, Cfg *cfg) {CharBUF[MAX_BUF] ="", Path[max_buf];//Open File dialog box, Openfiledlg::multi_open settings can open multiple files at the same time if(Openfiledlg (DLG, Openfiledlg::multi_open). Exec(BUF, Addfile_msgstr, OPENFILEALL_MSGSTR, cfg->lastopendir)! =TRUE)return FALSE;//Gets the path character length of the open file intDirlen = strlen (Cfg->lastopendir);//If only one file is selected, add the file directly to the buffer shareinfo of the file to be sent if(Buf[dirlen])returnSharemng->addfileshare (Shareinfo, buf);//If multiple files are selected, the loop adds each file to the file buffer to be sent for(Char*fname=buf+dirlen+1; *fname; FName + = strlen (fname) +1) {if(Makepath (Path, buf, fname) >= MAX_PATH)Continue; Sharemng->addfileshare (shareinfo, path); }return TRUE;}
The call to open a file dialog box is implemented by calling Win32 's API GetOpenFileName () function in exec in the Openfiledlg class.
2. Storage structure of files to be sent
From the Tsharedlg::fileadddlg function, you can see that the file to be sent is stored in SH
The Areinfo class. Shareinfo's statement is as follows
structShareinfo: PublicTlistobj {intPacketno;// Host **host;//List of destination machines to be sent inthostcnt;//number of destination machines to be sent Char*transstat;// FileInfo **fileinfo;//File information to transfer intfilecnt;//number of files to transferFILETIME Attachtime; ...}; Class FileInfo: PublicTlistobj {intId//ID of the file to transfer Char*fname;//File name Const Char*fname_ext;//For recv dir threadUINT attr;//file attributes, such as file or folder, read-only, etc._int64 size;//File sizetime_t Mtime;//File Last modifiedtime_t atime;//File last access timetime_t Crtime;//File creation timeBOOL isSelected;//For Recvdlg...}
Go back to Tsharedlg::fileadddlg, see Sharemng->addfileshare (Shareinfo, path);
BOOLSharemng::addfileshare (Shareinfo *info,Char*fname) {//If the file to be sent is already added to the list, it is no longer processed for(intCnt=0; CNT < info->filecnt; cnt++)if(strcmp (fname, info->fileinfo[cnt]->fname ()) = =0)return FALSE; FileInfo *fileinfo = new FileInfo;//Set new file information to be sent, such as file size, last modification time, etc. if(Setfileinfo (fname, fileInfo) = =FALSE)return FALSE;//If the memory allocated by FileInfo is exhausted, it needs to allocate more memory to hold the new file information if((info->filecnt% big_alloc) = =0) Info->fileinfo = (fileInfo * *) realloc (Info->fileinfo, (info->filecnt + big_alloc) *sizeof(FileInfo *)); INFO->FILEINFO[INFO->FILECNT] = FileInfo; info->filecnt++;return TRUE;}
3. File transfer in the network
(1) The format in which the file is transmitted on the network.
ID: FileName: File size: Last modified: File properties:
If more than one file is added, the information between multiple files is separated by a ' \a ' character.
(2) sendmsg in Senddlg.cpp, that is, press the "Send" button to trigger the event, the code is as follows
BOOL tsenddlg::sendmsg (void) {... if(shareinfo && shareinfo->filecnt) command |= ipmsg_fileattachopt;... if(Shareinfo && shareinfo->filecnt) {Char buf[max_udpbuf/2]; The file is generated (1) in the format encodesharemsg (shareinfo, buf, sizeof (BUF)); SHARESTR = new Char [strlen (BUF) +1]; strcpy (Sharestr, buf); Sharemng->addhostshare (Shareinfo, Sendentry, sendentrynum); } sendmsgsub ();...}bool encodesharemsg (Shareinfo *info, char *buf, int bufsize) {int offset=0; Char Fname[max_path]; *buf =0; for(int cnt=0; CNT < info->filecnt; cnt++) {forcepathtofname (Info->fileinfo[cnt]->fname (), Fname); Info->fileinfo[cnt]->setid (CNT); Offset + = wsprintf (buf + offset, (info->fileinfo[cnt]->size () >> +) ?"%d:%s:%x%08x:%x:%s":"%d:%s:%x%x:%x:", CNT, fname, (int) (Info->fileinfo[cnt]->size () >> +), (int) info->fileinfo[cnt]->size (), Info->fileinfo[cnt]->mtime ()); Offset + = wsprintf (buf + offset,"%x:", info->fileinfo[cnt]->attr ()); Offset + = wsprintf (buf + offset,"%c", Filelist_separator);if(offset + max_buf > BufSize) Break; }return TRUE;}
Sendmsgsub () encrypts the sent message (the transmitted file information is not encrypted).
BOOL TSendDlg::SendMsgSub(void){ for (int cnt=0; cnt < sendEntryNum; cnt++) { if (sendEntry[cnt].Status() == ST_MAKECRYPTMSG) { MakeEncryptPacket(sendEntry + cnt); } ... if (sendEntry[cnt].Status() == ST_SENDMSG) { const char *str = sendEntry[cnt].Msg() ? sendEntry[cnt].Msg() : msgBuf; int len = sendEntry[cnt].Msg() ? sendEntry[cnt].MsgLen() : packetLen; msgMng->UdpSend(sendEntry[cnt].Host()->hostSub.addr, sendEntry[cnt].Host()->hostSub.portNo, str, len); } ... }}
The following is a file sent using the Fly pigeon software
The red box in the figure is the file information you want to send, and you can see that the file name is open_data_structures.pdf, the file size is the hexadecimal 01817d0 byte, and the last modification time is hex 53f492fe.
4. Processing at the receiving end
Now just send the file information to send, but the actual file content has not been sent out. The transfer of the file contents is done via TCP.
UDP messages are processed by the Mainwin after receiving the UDP message sent. UDP is handled in the Udpevent function of Mainwin.cpp.
BOOL tmainwin::udpevent (LPARAM LPARAM) {msgbuf msg;if(Wsagetselecterror (lParam) | | msgmng->recv (&MSG)! =TRUE)return FALSE;... Switch(Get_mode (Msg.command)) {...Case IPMSG_SENDMSG://handling messages sent to Msgsendmsg (&MSG); Break;...}...}void tmainwin::msgsendmsg (Msgbuf *msg) {...Recvdlgopen (msg);...}bool Tmainwin::recvdlgopen (Msgbuf *msg) {Trecvdlg *recvdlg;... if(Recvdlg = new Trecvdlg (MSGMNG, MSG, &hosts, cfg, logmng) = =NULL)return FALSE;...Recvdlg->create (); Recvdlg->show (); Recvdlg->setforceforegroundwindow ();...}
The Receive dialog box opens when the message is received by the receiving side. Below is a look at the Receive dialog box's constructor and Receive dialog box Evcreate dialog box
Trecvdlg::trecvdlg (msgmng *_msgmng, Msgbuf *_msg, thosts *_hosts, Cfg *_cfg, logmng *_logmng): TListDlg (RECEIVE_DIALOG), Editsub (_cfg, this) {...Option command to transfer files in an optional fieldif(Msg.command & Ipmsg_fileattachopt) {//parse the information from the received message into the fileif((Shareinfo = decodesharemsg (Msg.msgbuf + msg.exoffset))! =NULL) {fileobj = new Recvfileobj; memset (Fileobj,0, sizeof (recvfileobj)); } }...}bool trecvdlg::evcreate (LPARAM LPARAM) {... if(Msg.command & ipmsg_secretopt):: ShowWindow (GetDlgItem (Recv_edit), Sw_hide),:: ShowWindow (GetDlgItem (Quote_che CK), sw_hide);Else{:: ShowWindow (GetDlgItem (Open_button), sw_hide), OPENFLG =TRUE; Display the file name in the buttonif(Shareinfo) Setfilebutton (This, File_button, shareinfo); }...}
Recvdlg as follows
In the dialog box that appears, click the "Open_data_structures.pdf" button. A dialog box will pop up to save the file. The transfer of the file will begin when the point is saved. About the specific transmission code analysis of the file, the next one in detail.
Fly Pigeon Biography Source Analysis five-file transfer