How to build a com to send and receive multi file by ATL
CodeWorrior April 24,2002.
Introduction
The CoM Can send and received Multi File from Server.
The Project Code Has Been Built With VC 6.0 SP5 / ATL3.0 AND TESTED ON WIN2K Professional.
Getting start
1.create an atl project by useing ATL COM AppWizard, Name It as what you want,
At The Step 1: Choose Support MFC;
2.INSERT New ATL Object By Menu / Toolbar, SELECT Control -> Lite Control ->
Names: Short name -> TestthRead
Attributes: Support isupp PorterrorInfo
Support connection_points
Interface -> DUAL
Thread Model -> Apartment
Misc: Invisible At Runtime
Then Click OK;
3. At ClassView, Right Cleick CTestthread Select Add Method,
Add Three Method and The .idl File Can Found Code Like Following Lines
Interface ITestthread: Idispatch
{
[ID (1), Helpstring ("Multithread Download File From Server)] HRESULT DOWNFILE ([In] BSTR BSTRSTRING);
[ID (2), Helpstring ("Show About")] HRESULT ABOUT ();
[ID (3), Helpstring ("Method SendFile")] HRESULT Sendfile ([in] BSTR BSTRSTRING, [IN] BSTR BSTRFILESTRING);
}
4.IN Testthread.cpp Add Following Codes:
// TestthRead.cpp: Implementation of Ctestthread
#include "stdafx.h"
#include "threadtest.h"
#include "testthread.h"
#include "aboutdlg.h"
/
// ctestthread
//
// Globally
Char * msg [10];
DWORD WINAPI ReceiveFile (LPVOID);
Csocket sockclient;
Socket_stream_file_info streamfileinfo;
// Global definition is completed
StdMethodimp Ctestthread :: DownFile (BSTR BSTRSTRING)
{
AFX_MANAGE_STATE (AFXGETSTATICModuleState ())
// Todo: Add Your Implementation Code Here
///
//
/ / Responsible for the download of the file, the message string is here to process
//
///
Uses_Conversion;
/ / Decompose the message string and send it to the server.
LPTSTR LPMSG;
LPMSG = OLE2T (BSTRSTRING);
Char * chmsgstring;
CHMSGSTRING = lpmsg;
Char * msg [10];
INT i = 0;
Char * split;
Split = strtok (chmsgstring, ":");
STRCPY (LPMSG, Split);
While (split! = NULL)
{
Split = strtok (null, ":");
IF (split! = null)
{
// MessageBox (Split, "Testsplitstring", MB_OK;
i = i 1;
MSG [I] = SPLIT;
// afxMessageBox (MSG [i]);
}
}
AfxSocketinit (NULL);
SockClient.create ();
IF (! SockClient.connect (lpmsg, 1028))
{
AfxMessageBox ("Connect to Server Fail!");
SockClient.Close ();
Return S_FALSE;
}
Try
{
Socket_userinfo userinfo; msg [] may need to change
STRCPY (UserInfo.uSername, MSG [1]);
STRCPY (UserInfo.database, MSG [2]);
STRCPY (UserInfo.docid, MSG [3]);
STRCPY (UserInfo.editmode, MSG [4]);
STRCPY (UserInfo.dotname, MSG [5]);
STRCPY (UserInfo.multiUser, MSG [6]);
STRCPY (UserInfo.attid, MSG [7]);
SockClient.send (& UserInfo, SIZEOF (Socket_UserInfo);
// Test code
// HRESULT HR = SockClient.Receive (& StreamFileinfo,
// sizeof (socket_stream_file_info);
//sockclient.receive (&userInfo ,sizeof(Socket_UserInfo);
While (1)
{
Handle hthread;
DWORD DWTHREADID;
Hthread = CreateThread (Null, 0, Receivefile, 0, 0, & DWTHREADID);
Sleep (5000);
:: WaitForsingleObject (Hthread, 200);
CloseHandle (HTHREAD);
Try
{
IF (SockClient.Receive ((void *) m_szbuffer, 4, 0))
{
//
//
// If you receive information, the comparison ends while "end".
// loop, otherwise continue looping to create a thread receiving file
//
//
STRCPY (M_SZFLAG, "END");
IF (m_szbuffer == m_szflag)
{
Break; // receive data == "end", exit while block
}
}
Else
///
//
// If you do not receive any information, exit the loop
//
//
Break;
}
Catch (...)
{
Break; // while catch error, break;
}
SockClient.Close ();
}
Catch (...)
{
ATLTRACE (_T ("test"));
SockClient.Close ();
Return S_FALSE;
}
:: sysfreestring (bstrstring);
Return S_OK;
}
DWORD WINAPI ReceiveFile (LPVOID P)
{
Coinitializeex (0, Coinit_Multithread);
// The following code can be accepted normally
//
SockClient.Receive (& StreamFileInfo, SIZEOF (socket_stream_file_info);
///
//
// Add code, determine if the received file name contains ".jpg", and set you
/ / The save the directory is "D: / ImgTemp /", not saved as "c: / info21 /"
//
///
:: Createdirectory (_T ("C: // Info21 ////////////////////////////////////////////////////////////////>
:: setCurrentDirectory (_t ("c: // info21 //)); // Set the directory of the download file
Try
{
//AFXMessageBox (streamfileinfo.szfiletitle);
Cfile destfile (streamfileinfo.szfileTitle, // Set the downloaded file name
CFILE :: Modecreate | CFile :: Modewrite | CFILE :: Typebinary
Uint dwread = 0; // Receive files
While (dwread { BYTE * DATA = New byte [1024]; // 1k blocks to the buffer MEMSET (DATA, 0, 1024); UINT DW = SockClient.Receive (Data, 1024); Destfile.write (DATA, DW); DWREAD = DW; } SetFileTime ((Handle) destfile.m_hfile, & streamfileinfo.ftcreationTIME, & Streamfileinfo.ftlastaccesstime, & StreamfileInfo.ftlastwritetime); SetFileAttributes (streamfileinfo.szfiletitle, streamfileinfo.dwfileAttribute); Destfile.close (); // One file receive over. } Catch (...) { MessageBox (NULL, _T ("Receive File Error !!"), _ T ("Receive File", MB_ICONITIONFORMATION | MB_OK); SockClient.Close (); AfxMessageBox ("File Download Failed!"); Return S_FALSE; } MessageBox (NULL, _T ("File All Received Complete !!", _ T ("Receive File", MB_OK); Couninitialize (); returnograph; } STDMETHODIMP CTESTHREAD :: About () { AFX_MANAGE_STATE (AFXGETSTATICModuleState ()) // Todo: Add Your Implementation Code Here /// // // Show About // /// Caboutdlg DLG; Dlg.domodal (); Return S_OK; } STDMETHODIMP CTESTTHREAD :: Sendfile (BSTR BSTRSTRING, BSTR BSTRFILESTRING) { AFX_MANAGE_STATE (AFXGETSTATICModuleState ()) // Todo: Add Your Implementation Code Here / // Send a file to the server / / Parameter is a message string (BSTRSTRING), file path (BStrfileString) /// Uses_Conversion; LPTSTR LPMSG; LPMSG = OLE2T (BSTRSTRING); Char * chmsgstring; CHMSGSTRING = lpmsg; Char * msg [10]; INT i = 0; Char * split; Split = strtok (chmsgstring, ":"); decomposition message string STRCPY (LPMSG, Split); While (split! = NULL) { Split = strtok (null, ":"); IF (split! = null) { // MessageBox (Split, "Testsplitstring", MB_OK; i = i 1; MSG [I] = SPLIT; // afxMessageBox (MSG [i]); } } AfxSocketinit (NULL); SockClient.create (); IF (! SockClient.connect (lpmsg, 1028)) { AfxMessageBox ("Connect to Server Fail!"); SockClient.Close (); Return S_FALSE; } Socket_userinfo userinfo; msg [] may need to change Server Agreement STRCPY (UserInfo.uSername, MSG [1]); STRCPY (UserInfo.database, MSG [2]); STRCPY (UserInfo.docid, MSG [3]); STRCPY (UserInfo.editmode, MSG [4]); STRCPY (UserInfo.dotname, MSG [5]); STRCPY (UserInfo.multiUser, MSG [6]); STRCPY (UserInfo.attid, MSG [7]); SockClient.send (& UserInfo, SIZEOF (Socket_UserInfo); // :: setCurrentDirectory (BStrfileString); Recurse (bstrfilestring); / / Search for files in the specified directory and transfer to the server SockClient.Close (); :: sysfreestring (bstrstring); :: sysfreestring (bstrfilestring); Return S_OK; } Void Ctestthread :: Recurse (BSTR Filepath) { Uses_Conversion; cfilefind enough; BSTR PSTR = filepath; // Find conditions CString StrwildCard (PSTR); StrwildCard = _t ("//*.*"); Bool BWORKING = Finder.findfile (StrwildCard); While (BWORKING) { BWORKING = Finder.findnextFile (); // // Output file name CString strfilename = finder.getfilepath (); IF (StrfileName! = ".") { IF (strfilename! = "))) { Sendfile (T2OLE (StrfileName); } } } Finder.Close (); :: Sysfreestring (FilePath); } HRESULT CTESTHREAD :: Sendfile (BSTR Docfile) { Uses_Conversion; Char * filename = ole2t (docfile); Cfile myfile; IF (! myfile.open (filename, / * conversion bstr to char * * / Cfile :: ModeRead | CFILE :: TypeBinary)) { // The file opens failed to return directly. In "." And ".." The two directory files appear. Return 0; } Socket_stream_file_info streamfileinfo; Win32_find_data findfiledata; FindClose (MyFile.GetFilePath (), & FindFileData); MEMSET (& Streamfileinfo, 0, SIZEOF (socket_stream_file_info); Strcpy (streamfileinfo.szfileTitle, MyFile.GetFileName ()); Streetfileinfo.nfilesizelow = findfiledata.nfilesizer; SockClient.send (& StreamFileInfo, Sizeof (socket_stream_file_info); Uint dwread = 0; While (dwread { BYTE * DATA = New byte [5120]; Uint dw = myfile.read (data, 5120); SockClient.send (DATA, DW); DWREAD = DW; } myfile.close (); :: sysfreeestring (docfile); Return S_OK; } For the About Method, You Must Add A Dialog and Named Aboutdlg, OK. User Define struct must be add to testthread.h file: Typedef struct _socket_stream_file_info { Tchar SzfileTitle [128]; DWORD DWFILEATTRIBUTES; Filetime FTCREATIONTIME; Filetime ftlastaccesstime; Filetime ftlastwrittime; DWORD NFILESIGHIGH; DWORD NFILESZELOW; DWORD dwreserved0; DWORD dwreserved1; } Socket_Stream_File_info, * psocket_stream_file_info; Typedef struct _socket_userinfo { Tchar Username [128]; TCHAR DATABASE [128]; TCHAR DOCID [256]; TCHAR Attid [256]; Tchar dotname [128]; Tchar Multiuser [128]; Tchar EditMode [128]; TCHAR USERTIME [128]; } Socket_UserInfo, * psocket_userinfo; FOLLOWING TWO Variable Must Be Add to Ctestthread Class Char m_szbuffer [4]; Char m_szflag [4]; Add #include "AfXSock.h" to stdafx.h file Happy programing. :-) Good luck !!! Contract me, please mail to: codeWorrior@hotmail.com. If you need song code, give me your e_mail address! !