Source code analysis-File Transfer-source code
Reprinted please indicate the source:Http://blog.csdn.net/mxway/article/details/44889871
This article is based on the source code v2.06.
1. Add the file to be sent
The file is sent in the send dialog box. First, find the shortcut menu of the send dialog box.
The menu id corresponding to File Transfer is MENU_FILEADD. The corresponding command Processing Event Is In The EvCommand function of Senddlg. cpp.
BOOL TSendDlg: EvCommand (WORD wNotifyCode, WORD wID, LPARAM hWndCtl) {switch (wID) {case MENU_FILEADD: {char buf [MAX_PATH] = ""; if (TShareDlg :: fileAddDlg (this, shareMng, cmdinfo? Raise info: (raise info = shareMng-> CreateShare (packetNo), cfg) {SetFileButton (this, FILE_BUTTON, raise info); EvSize (SIZE_RESTORED, 0, 0 );}} break ;}} BOOL TShareDlg: FileAddDlg (TDlg * dlg, ShareMng * shareMng, raise info * Raise info, Cfg * cfg) {char buf [MAX_BUF] = "", path [MAX_BUF]; // open the file dialog box. OpenFileDlg: MULTI_OPEN allows you to open multiple files simultaneously if (OpenFileDlg (dlg, OpenFileDlg: MULTI_OPEN ). exec (buf, ADDFILE_MSGSTR, OPENFILEALL_MSGSTR, cfg-> lastOpenDir )! = TRUE) return FALSE; // obtain the path character length of the open file. int dirlen = strlen (cfg-> lastOpenDir); // if only one file is selected, directly add the file to the cache region of the file to be sent. if (buf [dirlen]) return shareMng-> AddFileShare (partition info, buf); // if multiple files are selected, add each file to the cache of the file to be sent in a loop for (char * fname = buf + dirlen + 1; * fname; fname + = strlen (fname) + 1) {if (MakePath (path, buf, fname)> = MAX_PATH) continue; shareMng-> AddFileShare (cmdinfo, path);} return TRUE ;}
The open file dialog box is implemented by calling the Win32 API GetOpenFileName () function in Exec of the OpenFileDlg class.
2. Storage Structure of the file to be sent
From the TShareDlg: FileAddDlg function, you can see that the file to be sent is stored in Sh.
AreInfo class. The statement of raise info is as follows:
Struct failed info: public TListObj {int packetNo; // Host ** host; // list of destination machines to be sent int hostCnt; // number of destination machines to be sent char * transStat; // FileInfo ** fileInfo; // The object information to be transmitted int fileCnt; // The number of objects to be transmitted FILETIME attachTime ;...}; class FileInfo: public TListObj {int id; // id of the file to be transmitted char * fname; // file name const char * fname_ext; // for recv dir thread UINT attr; // file attributes, such as file or folder, read-only _ int64 size; // file size time_t mtime; // The last modification time of the file time_t atime; // file last access time time_t crtime; // File Creation Time BOOL isSelected; // for recvdlg ...}
Go back to TShareDlg: FileAddDlg and check shareMng-> AddFileShare (cmdinfo, path );
BOOL ShareMng: AddFileShare (partition info * info, char * fname) {// if the file to be sent has been added to the list, it will not be processed for (int cnt = 0; cnt <info-> fileCnt; cnt ++) if (strcmp (fname, info-> fileInfo [cnt]-> Fname () = 0) return FALSE; fileInfo * fileInfo = new FileInfo; // set the information of the new file to be sent, such as the file size and last modification time. if (SetFileInfo (fname, fileInfo) = FALSE) return FALSE; // if the memory allocated by fileInfo is used up, allocate more memory to store 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 transmission over the network
(1) Format of file transfer over the network.
Id: File Name: file size: last modification time: file attributes:
If multiple files exist, the information of multiple files is separated by the '\ a' character.
(2) In Senddlg. cpp, SendMsg is the trigger event by pressing the "Send" button. The Code is as follows:
BOOL TSendDlg: SendMsg (void ){... if (fileCnt) command | = IPMSG_FILEATTACHOPT ;... if (cmdinfo & cmdinfo-> fileCnt) {char buf [MAX_UDPBUF/2]; // format EncodeShareMsg (cmdinfo, buf, sizeof (buf); shareStr = new char [strlen (buf) + 1]; strcpy (shareStr, buf); shareMng-> AddHostShare (cmdinfo, sendEntry, sendEntryNum );} sendMsgSub ();...} BOOL EncodeShareMsg (memory in Fo * 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 ()> 32 )? "% D: % s: % x % 08x: % x: % s": "% d: % s: % x:", cnt, fname, (int) (info-> fileInfo [cnt]-> Size ()> 32), (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 messages (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 Flying Pigeon transfer software.
The file information to be sent in the red box in the figure. It can be seen that the name of the sent file is open_data_structures.pdf. The file size is 01817d0 in hexadecimal format, and the last modification time is 53f492fe in hexadecimal format.
4. acceptor Processing
Currently, only the file information to be sent is sent, but the actual file content has not been transferred. The file content is transmitted over TCP.
After receiving the sent udp message, Mainwin processes the udp message. Udp is processed 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: // process the sent message 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 ();...}
After receiving a message, the receiving dialog box is displayed. The following describes the constructor of the receiving dialog box and the EvCreate dialog box of the receiving dialog box.
TRecvDlg: TRecvDlg (MsgMng * _ msgMng, MsgBuf * _ msg, THosts * _ hosts, Cfg * _ cfg, LogMng * _ logmng): TListDlg (RECEIVE_DIALOG ), editSub (_ cfg, this ){... // if (msg. command & IPMSG_FILEATTACHOPT) {// parse the file information from the received message if (incluinfo = DecodeShareMsg (msg. msgBuf + msg. exOffset ))! = NULL) {fileObj = new RecvFileObj; memset (fileObj, 0, sizeof (RecvFileObj ));}}...} BOOL TRecvDlg: EvCreate (LPARAM lParam ){... if (msg. command & Response): ShowWindow (GetDlgItem (RECV_EDIT), SW_HIDE),: ShowWindow (GetDlgItem (QUOTE_CHECK), SW_HIDE); else {: ShowWindow (GetDlgItem (OPEN_BUTTON ), SW_HIDE), openFlg = TRUE; // display the file name to the button if (Response info) SetFileButton (this, FILE_BUTTON, response info );}...}
RecvDlg is as follows
Click the export open_data_structures.pdf button in the displayed dialog box. A dialog box for saving files is displayed. After you click Save, the file transmission starts. For details about the specific file transfer code analysis, the next article will be detailed.