How to build a COM to Send and Receive Multi File by ATL

    技术2022-05-11  152

    How to build a COM to Send and Receive Multi File by ATL

     

    CodeWorrior April 24,2002.

     

    Introduction

     

    The COM can send and receive Multi file from Server .

    The project code has been built with VC++ 6.0 SP5 / ATL3.0 and tested on Win2K Professional.

     

    Getting started

     

    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 ISupportErrorInfo

                           support Connection_Points

                           interface -->Dual

                                 thread model -->Apartment

                    Misc:  inVisible at runtime

          then click ok;

     

    3. At classview ,right click 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

     

    //

    //     全局

    char* msg[10];

     

    DWORD WINAPI ReceiveFile(LPVOID);

     

    CSocket sockClient;

     

    SOCKET_STREAM_FILE_INFO StreamFileInfo;

     

    // 全局定义完毕

     

    STDMETHODIMP CTestThread::DownFile(BSTR bstrString)

    {

           AFX_MANAGE_STATE(AfxGetStaticModuleState())

     

           // TODO: Add your implementation code here

          

           ///

          //

          //     负责文件的下载工作,消息字符串在这里需要处理

          //

            ///

           USES_CONVERSION;  

         

          //分解消息串,并发送给服务器。

          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[]次序可能需要变动

                                       

                  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));

     

                  //测试用代码

                  //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))

                                {

                                       //

                                       //

                                       //       如果接收到信息,则比较,为"end"则结束while

                                       //  循环,否则继续循环创建线程接收文件

                                       //

                                       //

                                       strcpy(m_szFlag,"end");  

                                       if(m_szBuffer == m_szFlag)

                                       {

                                              break;           //Receive Data =="end" ,Exit While Block

                                       }

                                }

                                else

                                       ///

                                       //

                                       //       如果没有接收到任何信息,退出循环

                                       //    

                                       //

                                       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_MULTITHREADED);

          

           //   以下代码经过测试可以正常接受文件

           //

     

           sockClient.Receive(&StreamFileInfo,sizeof(SOCKET_STREAM_FILE_INFO));

     

           ///

           //

           //     添加代码,判断接收到的文件名是否含有".JPG",有则设置你

           //  保存目录为 "d:/imgtemp/" ,不是则保存为 "c:/info21/"

           //  

           ///

     

           ::CreateDirectory(_T("C://Info21//"),NULL);

           ::SetCurrentDirectory(_T("C://Info21//"));         //设置下载文件的目录

          

           try

           {                         

                  //AfxMessageBox(StreamFileInfo.szFileTitle);

                  CFile destFile(StreamFileInfo.szFileTitle ,//设置下载后的文件名

                         CFile::modeCreate | CFile::modeWrite | CFile::typeBinary);

                  UINT dwRead = 0;                           //接收文件

                  while(dwRead<StreamFileInfo.nFileSizeLow)

                  {

                         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.dwFileAttributes);

                 

                  destFile.Close();                            // One File Receive over.

           }

           catch(...)

           {

               MessageBox(NULL,_T("Receive File Error!! And Socket Will DisConnect!!"),_T("Receive File"),       MB_ICONINFORMATION|MB_OK);

                  sockClient.Close();

                  AfxMessageBox("文件下载失败!");

                  return S_FALSE;

           }

           MessageBox(NULL,_T("File All Received Complete!!"),_T("Receive File"),MB_OK);

           CoUninitialize();

           return 0;

    }

     

    STDMETHODIMP CTestThread::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

                 

           /

           //     发送文件到服务器

           //  参数为  消息串(bstrString),文件路径(bstrFileString)

           ///

           USES_CONVERSION;

          

           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;

           }

          

           SOCKET_USERINFO UserInfo;              msg[]次序可能需要变动

                                                   与服务器协定

           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);           //搜索指定目录下的文件并传送到服务器

     

           sockClient.Close();

           ::SysFreeString(bstrString);

           ::SysFreeString(bstrFileString);

           return S_OK;

    }

     

    void CTestThread::Recurse(BSTR  FilePath)

    {

       USES_CONVERSION;

       CFileFind finder;

     

       BSTR pstr = FilePath; 

      

           //查找条件

       CString strWildcard(pstr);

       strWildcard += _T("//*.*");

     

       BOOL bWorking = finder.FindFile(strWildcard);

      

       while (bWorking)

       {

          bWorking = finder.FindNextFile();

     

          //

          // 输出文件名

             CString strFilename = finder.GetFilePath();

            

            

             if(strFilename!= ".")

             {

                    if(strFilename!="..")

                    {

                        

                         SendFile(T2OLE(strFilename));                   

                    }

              }

            

       }

     

       finder.Close();

       ::SysFreeString(FilePath);

    }

     

     

    HRESULT CTestThread::SendFile(BSTR DocFile)

    {

           USES_CONVERSION;

           char* filename = OLE2T(DocFile);

     

           CFile myFile;

           if(!myFile.Open( filename ,/* conversion BSTR to char* */

                                       CFile::modeRead | CFile::typeBinary))

           {

                  //文件打开失败直接返回。在 " . " and " .. " 两个目录文件的情况下出现。

                  return 0;

           }

     

           SOCKET_STREAM_FILE_INFO              StreamFileInfo;

           WIN32_FIND_DATA             FindFileData;

     

        FindClose(FindFirstFile(myFile.GetFilePath(),&FindFileData));

        memset(&StreamFileInfo,0,sizeof(SOCKET_STREAM_FILE_INFO));

        strcpy(StreamFileInfo.szFileTitle,myFile.GetFileName());

     

        StreamFileInfo.nFileSizeLow         =       FindFileData.nFileSizeLow;     

     

           sockClient.Send(&StreamFileInfo,sizeof(SOCKET_STREAM_FILE_INFO));    

     

           UINT dwRead=0;

           while(dwRead<StreamFileInfo.nFileSizeLow)

           {

                  byte* data = new byte[5120];

                  UINT dw=myFile.Read(data, 5120);

                  sockClient.Send(data, dw);

                  dwRead+=dw;

           }

           myFile.Close();

          

           ::SysFreeString(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    ftLastWriteTime;                   

        DWORD       nFileSizeHigh;                     

        DWORD       nFileSizeLow;                      

        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 programming. :-)

    Good Luck!!!  Contract me ,please mail to : CodeWorrior@hotmail.com.

    If you need  Source Code ,Give me your e_mail address !!


    最新回复(0)