socket 发送文件

服务器端:
  1. UINT CFileTransferServerView::ThreadedSendFileToRemoteRecipient(LPVOID pVoid)
  2. {
  3.     CFileTransferServerView* pThis = (CFileTransferServerView*)pVoid;
  4.     pThis->PostMessage( UWM_FILESENDEVENT, FSE_THREADSTART, 0L );
  5.     
  6.     AfxSocketInit(NULL);    // make certain this is done somewhere in each thread (usually in InitInstance for main thread)
  7.     CSocket sockSrvr; 
  8.     sockSrvr.Create(PRE_AGREED_PORT); // Creates our server socket
  9.     sockSrvr.Listen(); // Start listening for the client at PORT
  10.     CSocket sockConnection;
  11.     sockSrvr.Accept(sockConnection); // Use another CSocket to accept the connection
  12.     
  13.     pThis->PostMessage( UWM_FILESENDEVENT, FSE_STATUSCONNECTED, 0L );
  14.     
  15.     // local variables used in file transfer (declared here to avoid "goto skips definition"-style compiler errors)
  16.     int fileLength, cbLeftToSend;   // used to monitor the progress of a sending operation
  17.     int simulate;   // used to simulate mismatch events (if designated by user)
  18.     
  19.     BYTE* sendData = NULL;  // pointer to buffer for sending data (memory is allocated after sending file size)
  20.     
  21.     int pbInterval = 0; int curPB = 0;  // progress bar variables
  22.     
  23.     
  24.     CFile sourceFile;
  25.     CFileException fe;
  26.     BOOL bFileIsOpen = FALSE;
  27.     
  28.     if( !( bFileIsOpen = sourceFile.Open( pThis->m_strFileName, CFile::modeRead | CFile::typeBinary, &fe ) ) )
  29.     {
  30.         TCHAR strCause[256];
  31.         fe.GetErrorMessage( strCause, 255 );
  32.         TRACE( "SendFileToRemoteRecipient encountered an error while opening the local file/n"
  33.             "/tFile name = %s/n/tCause = %s/n/tm_cause = %d/n/tm_IOsError = %d/n",
  34.             fe.m_strFileName, strCause, fe.m_cause, fe.m_lOsError );
  35.         /* you should handle the error here */
  36.         goto PreReturnCleanup;
  37.     }
  38.     
  39.     
  40.     // first send length of file
  41.     
  42.     fileLength = sourceFile.GetLength();
  43.     fileLength = htonl( fileLength );
  44.     
  45.     cbLeftToSend = sizeof( fileLength );
  46.     
  47.     // Inject mismatch events (if selected by user)
  48.     // Seed the random-number generator with current time 
  49.     srand( (unsigned)time( NULL ) );
  50.     
  51.     simulate = 1 + rand() % 2;  // either 1 or 2
  52.     simulate = ( pThis->m_bSimulateEvents ) ? simulate : 0; // zero if user de-selected event simulation
  53.     
  54.     do
  55.     {
  56.         int cbBytesSent;
  57.         BYTE* bp = (BYTE*)(&fileLength) + sizeof(fileLength) - cbLeftToSend;
  58.         cbBytesSent = sockConnection.Send( bp, cbLeftToSend - simulate );
  59.         simulate = 0;
  60.         
  61.         // test for errors and get out if they occurred
  62.         if ( cbBytesSent == SOCKET_ERROR )
  63.         {
  64.             int iErr = ::GetLastError();
  65.             TRACE( "SendFileToRemoteRecipient returned a socket error while sending file length/n"
  66.                 "/tNumber of Bytes sent = %d/n"
  67.                 "/tGetLastError = %d/n", cbBytesSent, iErr );
  68.             
  69.             /* you should handle the error here */
  70.             
  71.             goto PreReturnCleanup;
  72.         }
  73.         
  74.         // data was successfully sent, so account for it with already-sent data
  75.         cbLeftToSend -= cbBytesSent;
  76.     }
  77.     while ( cbLeftToSend>0 );
  78.     
  79.     
  80.     // now send the file's data
  81.     
  82.     sendData = new BYTE[SEND_BUFFER_SIZE]; 
  83.     
  84.     cbLeftToSend = sourceFile.GetLength();
  85.     
  86.     
  87.     // set up progress bar
  88.     
  89.     fileLength = cbLeftToSend;
  90.     pbInterval = fileLength>>7;     // divide by 128
  91.     curPB = 0;
  92.     
  93.     pThis->m_ctlProgressSend.PostMessage( PBM_SETPOS, (WPARAM) curPB, 0L );
  94.     
  95.     do
  96.     {
  97.         // read next chunk of SEND_BUFFER_SIZE bytes from file
  98.     
  99.         int sendThisTime, doneSoFar, buffOffset;
  100.         
  101.         sendThisTime = sourceFile.Read( sendData, SEND_BUFFER_SIZE );
  102.         buffOffset = 0;
  103.         
  104.         // simulate mismatch events
  105.         
  106.         simulate = rand();
  107.         simulate = ( simulate>RAND_MAX/10 ) ? 0 : 2560*simulate/RAND_MAX ;  // up to 256 but only inject mismatches 10% of the time
  108.         simulate = ( pThis->m_bSimulateEvents ) ? simulate : 0 ;    // zero if user de-selected event simulation
  109.         
  110.         do
  111.         {
  112.             doneSoFar = sockConnection.Send( sendData + buffOffset, sendThisTime - simulate ); 
  113.             simulate = 0;
  114.             
  115.             // test for errors and get out if they occurred
  116.             if ( doneSoFar == SOCKET_ERROR )
  117.             {
  118.                 int iErr = ::GetLastError();
  119.                 TRACE( "SendFileToRemoteRecipient returned a socket error while sending chunked file data/n"
  120.                     "/tNumber of Bytes sent = %d/n"
  121.                     "/tGetLastError = %d/n", doneSoFar, iErr );
  122.                 
  123.                 /* you should handle the error here */
  124.                 
  125.                 goto PreReturnCleanup;
  126.             }
  127.             
  128.             // data was successfully sent, so account for it with already-sent data
  129.             // but first, advise main thread of a send mismatch if everything was not sent in one shot
  130.             
  131.             if ( doneSoFar != sendThisTime )
  132.             {
  133.                 pThis->m_iNumMismatches++;
  134.                 pThis->PostMessage( UWM_FILESENDEVENT, FSE_UPDATECONTROLS, 0L );
  135.             }
  136.             
  137.             buffOffset += doneSoFar;
  138.             sendThisTime -= doneSoFar;
  139.             cbLeftToSend -= doneSoFar;
  140.         }
  141.         while ( sendThisTime > 0 );
  142.         
  143.         // update progress bar
  144.         
  145.         if ( pbInterval*curPB < (fileLength-cbLeftToSend) )
  146.         {
  147.             curPB++;
  148.             pThis->m_ctlProgressSend.PostMessage( PBM_SETPOS, (WPARAM) curPB, 0L );
  149.         }
  150.         
  151.     }
  152.     while ( cbLeftToSend > 0 );
  153.     
  154.     
  155. PreReturnCleanup:       // labelled goto destination
  156.     
  157.     // free allocated memory
  158.     // if we got here from a goto that skipped allocation, delete of NULL pointer
  159.     // is permissible under C++ standard and is harmless
  160.     delete[] sendData;
  161.     
  162.     if ( bFileIsOpen )
  163.         sourceFile.Close();     // only close file if it's open (open might have failed above)
  164.     
  165.     sockConnection.Close();
  166.     
  167.     // advise main thread that we're completed
  168.     pThis->PostMessage( UWM_FILESENDEVENT, FSE_THREADCOMPLETE, 0L );
  169.     
  170.     return 0;
  171.     
  172. }

 

客户端:

  1. UINT CFileTransferClientView::ThreadedGetFileFromRemoteSender(LPVOID pVoid)
  2. {
  3.     CFileTransferClientView* pThis = (CFileTransferClientView*)pVoid;
  4.     
  5.     // advise main thread that this thread has started
  6.     
  7.     pThis->PostMessage( UWM_GETFILEEVENT, GFE_THREADSTART, 0L );
  8.     
  9.     // create client socket and connect to server
  10.     AfxSocketInit(NULL);    // make certain this is done somewhere in each thread (usually in InitInstance for main thread)
  11.     CSocket sockClient;
  12.     sockClient.Create();
  13.     
  14.     sockClient.Connect( pThis->m_strTargetIP, PRE_AGREED_PORT );    // PRE_AGREED_PORT is #define'd as 8686
  15.     pThis->PostMessage( UWM_GETFILEEVENT, GFE_STATUSCONNECTED, 0L );
  16.     // local variables used in file transfer (declared here to avoid "goto skips definition"-style compiler errors)
  17.     int dataLength, cbBytesRet, cbLeftToReceive;    // used to monitor the progress of a receive operation
  18.     int simulate;       // used to simulate mismatch events (if designated by user)
  19.     BYTE* recdData = NULL;  // pointer to buffer for receiving data (memory is allocated after obtaining file size)
  20.     int pbInterval = 0; int curPB = 0;  // progress bar variables
  21.     CFile destFile;
  22.     CFileException fe;
  23.     BOOL bFileIsOpen = FALSE;
  24.     
  25.     // open/create target file that receives the transferred data
  26.     if( !( bFileIsOpen = destFile.Open( pThis->m_strFileName, 
  27.         CFile::modeCreate | CFile::modeWrite | CFile::typeBinary, &fe ) ) )
  28.     {
  29.         TCHAR strCause[256];
  30.         fe.GetErrorMessage( strCause, 255 );
  31.         TRACE( "GetFileFromRemoteSender encountered an error while opening the local file/n"
  32.             "/tFile name = %s/n/tCause = %s/n/tm_cause = %d/n/tm_IOsError = %d/n",
  33.             fe.m_strFileName, strCause, fe.m_cause, fe.m_lOsError );
  34.         /* you should handle the error here */
  35.         goto PreReturnCleanup;
  36.     }
  37.     // get the file's size first
  38.     
  39.     cbLeftToReceive = sizeof( dataLength );
  40.     // Inject mismatch events (if selected by user)
  41.     // Seed the random-number generator with current time 
  42.     srand( (unsigned)time( NULL ) );
  43.     simulate = 1 + rand() % 2;  // either 1 or 2
  44.     simulate = ( pThis->m_bSimulateEvents ) ? simulate : 0; // zero if user de-selected event simulation
  45.     do
  46.     {
  47.         BYTE* bp = (BYTE*)(&dataLength) + sizeof(dataLength) - cbLeftToReceive;
  48.         cbBytesRet = sockClient.Receive( bp, cbLeftToReceive - simulate );
  49.         simulate = 0;
  50.         // test for errors and get out if they occurred
  51.         if ( cbBytesRet == SOCKET_ERROR || cbBytesRet == 0 )
  52.         {
  53.             int iErr = ::GetLastError();
  54.             TRACE( "GetFileFromRemoteSite returned a socket error while getting file length/n"
  55.                 "/tNumber of Bytes received (zero means connection was closed) = %d/n"
  56.                 "/tGetLastError = %d/n", cbBytesRet, iErr );
  57.             
  58.             /* you should handle the error here */
  59.             
  60.             goto PreReturnCleanup;
  61.         }
  62.         // good data was retrieved, so accumulate it with already-received data
  63.         cbLeftToReceive -= cbBytesRet;
  64.     }
  65.     while ( cbLeftToReceive > 0 );
  66.     dataLength = ntohl( dataLength );
  67.     
  68.     // set up progress bar based on expected length of file
  69.     pbInterval = dataLength>>7;     // divide by 128
  70.     curPB = 0;
  71.     pThis->m_ctlProgressGet.PostMessage( PBM_SETPOS, (WPARAM) curPB, 0L );
  72.     // now get the file in RECV_BUFFER_SIZE chunks at a time
  73.     
  74.     recdData = new byte[RECV_BUFFER_SIZE];
  75.     cbLeftToReceive = dataLength;
  76.     
  77.     do
  78.     {   
  79.         int iiGet, iiRecd;
  80.         // simulate mismatch events
  81.         
  82.         simulate = rand();
  83.         simulate = ( simulate>RAND_MAX/10 ) ? 0 : 2560*simulate/RAND_MAX ;  // up to 256 but only inject mismatches 10% of the time
  84.         simulate = ( pThis->m_bSimulateEvents ) ? simulate : 0 ;    // zero if user de-selected event simulation
  85.         
  86.         iiGet = (cbLeftToReceive<RECV_BUFFER_SIZE) ? cbLeftToReceive : RECV_BUFFER_SIZE ;
  87.         iiRecd = sockClient.Receive( recdData, iiGet - simulate );
  88.         simulate = 0;
  89.         
  90.         // test for errors and get out if they occurred
  91.         if ( iiRecd == SOCKET_ERROR || iiRecd == 0 )
  92.         {
  93.             int iErr = ::GetLastError();
  94.             TRACE( "GetFileFromRemoteSite returned a socket error while getting chunked file data/n"
  95.                 "/tNumber of Bytes received (zero means connection was closed) = %d/n"
  96.                 "/tGetLastError = %d/n", iiRecd, iErr );
  97.             /* you should handle the error here */
  98.             
  99.             goto PreReturnCleanup;
  100.         }
  101.         // good data was retrieved, so accumulate it with already-received data
  102.         // but first, advise main thread of a receive mismatch if we have not yet received everything expected
  103.         if ( iiGet != iiRecd )
  104.         {
  105.             pThis->m_iNumMismatches++;
  106.             pThis->PostMessage( UWM_GETFILEEVENT, GFE_UPDATECONTROLS, 0L );
  107.         }
  108.         destFile.Write( recdData, iiRecd); // Write it
  109.         cbLeftToReceive -= iiRecd;
  110.         // update progress bar
  111.         if ( pbInterval*curPB < (dataLength-cbLeftToReceive) )
  112.         {
  113.             curPB++;
  114.             pThis->m_ctlProgressGet.PostMessage( PBM_SETPOS, (WPARAM) curPB, 0L );
  115.         }
  116.     } 
  117.     while ( cbLeftToReceive > 0 );
  118.     
  119. PreReturnCleanup:       // labelled "goto" destination
  120.     // free allocated memory
  121.     // if we got here from a goto that skipped allocation, delete of NULL pointer
  122.     // is permissible under C++ standard and is harmless
  123.     delete[] recdData;      
  124.     if ( bFileIsOpen )
  125.         destFile.Close();   // only close file if it's open (open might have failed above)
  126.     sockClient.Close();
  127.     pThis->PostMessage( UWM_GETFILEEVENT, GFE_THREADCOMPLETE, 0L );
  128.     
  129.     return 0;
  130. }

这个程序是从服务器发送数据到客户端,第一步先发送要发送的文件的大小.然后才开始发送文件.

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值