⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filetransferclientview.cpp

📁 vc++网络程序设计实例详解 人民邮电出版社1-2章源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:

		strTemp = strIP.Mid( 0, nDex);
		strIP = strIP.Mid( nDex+1 );
		b[ii] = atoi( strTemp );

	}

	b[3] = atoi( strIP );

	if ( bErr )
	{
		m_ctlTargetIP.SetAddress( b[0], b[1], b[2], b[3] );
	}
*/

}

#define PRE_AGREED_PORT		8686
#define RECV_BUFFER_SIZE	4096

BOOL CFileTransferClientView::GetFileFromRemoteSender(CString strIP, CString fName)
{
	/***************************
	// connects to a remote server and downloads a file from it
	// the remote server must be running a counterpart SendFileToRemoteRecipient function
	// Inputs: CString strIP = IP address of remote server, in dotted IP format (like "127.0.0.1") or a manchine name (like "localhost")
	//         CString fName = name of local file to which downlaoded data will be stored
	// Output: BOOL return value indiactes success or failure of the download
	****************************/

	// create client socket and connect to server
	
///	AfxSocketInit(NULL);	// make certain this is done somewhere in each thread (usually in InitInstance for main thread)
	CSocket sockClient;
	sockClient.Create();
	
	sockClient.Connect( strIP, PRE_AGREED_PORT );	// PRE_AGREED_PORT is #define'd as 8686
	
	
	// local variables used in file transfer (declared here to avoid "goto skips definition"-style compiler errors)
	
	BOOL bRet = TRUE;								// return value
	
	int dataLength, cbBytesRet, cbLeftToReceive;	// used to monitor the progress of a receive operation
	
	BYTE* recdData = NULL;	// pointer to buffer for receiving data (memory is allocated after obtaining file size)
	
	CFile destFile;
	CFileException fe;
	BOOL bFileIsOpen = FALSE;
	
	// open/create target file that receives the transferred data
	
	if( !( bFileIsOpen = destFile.Open( fName, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary, &fe ) ) )
	{
		TCHAR strCause[256];
		fe.GetErrorMessage( strCause, 255 );
		TRACE( "GetFileFromRemoteSender encountered an error while opening the local file\n"
			"\tFile name = %s\n\tCause = %s\n\tm_cause = %d\n\tm_IOsError = %d\n",
			fe.m_strFileName, strCause, fe.m_cause, fe.m_lOsError );
		
		/* you should handle the error here */
		
		bRet = FALSE;
		goto PreReturnCleanup;
	}
	
	
	// get the file's size first
	
	cbLeftToReceive = sizeof( dataLength );
	
	do
	{
		BYTE* bp = (BYTE*)(&dataLength) + sizeof(dataLength) - cbLeftToReceive;
		cbBytesRet = sockClient.Receive( bp, cbLeftToReceive );
		
		// test for errors and get out if they occurred
		if ( cbBytesRet == SOCKET_ERROR || cbBytesRet == 0 )
		{
			int iErr = ::GetLastError();
			TRACE( "GetFileFromRemoteSite returned a socket error while getting file length\n"
				"\tNumber of Bytes received (zero means connection was closed) = %d\n"
				"\tGetLastError = %d\n", cbBytesRet, iErr );
			
			/* you should handle the error here */
			
			bRet = FALSE;
			goto PreReturnCleanup;
		}
		
		// good data was retrieved, so accumulate it with already-received data
		cbLeftToReceive -= cbBytesRet;
		
	}
	while ( cbLeftToReceive > 0 );
	
	dataLength = ntohl( dataLength );
	
	
	// now get the file in RECV_BUFFER_SIZE chunks at a time
	
	recdData = new byte[RECV_BUFFER_SIZE];
	cbLeftToReceive = dataLength;
	
	do
	{	
		int iiGet, iiRecd;
		
		iiGet = (cbLeftToReceive<RECV_BUFFER_SIZE) ? cbLeftToReceive : RECV_BUFFER_SIZE ;
		iiRecd = sockClient.Receive( recdData, iiGet );
		
		// test for errors and get out if they occurred
		if ( iiRecd == SOCKET_ERROR || iiRecd == 0 )
		{
			int iErr = ::GetLastError();
			TRACE( "GetFileFromRemoteSite returned a socket error while getting chunked file data\n"
				"\tNumber of Bytes received (zero means connection was closed) = %d\n"
				"\tGetLastError = %d\n", iiRecd, iErr );
			
			/* you should handle the error here */
			
			bRet = FALSE;
			goto PreReturnCleanup;
		}

/*************************	
  un-comment this code and put a breakpoint here to prove to yourself that sockets can return fewer bytes than requested
		  
			if ( iiGet != iiRecd )
			{
			int ii=0;
			}			
***************************/
		
		// good data was retrieved, so accumulate it with already-received data
		
		destFile.Write( recdData, iiRecd); // Write it
		cbLeftToReceive -= iiRecd;
		
	} 
	while ( cbLeftToReceive > 0 );
	
	
PreReturnCleanup:		// labelled "goto" destination
	
	// free allocated memory
	// if we got here from a goto that skipped allocation, delete of NULL pointer
	// is permissible under C++ standard and is harmless
	delete[] recdData;		
	
	if ( bFileIsOpen )
		destFile.Close();	// only close file if it's open (open might have failed above)
	
	sockClient.Close();
	
	return bRet;
}


UINT CFileTransferClientView::ThreadedGetFileFromRemoteSender(LPVOID pVoid)
{
	CFileTransferClientView* pThis = (CFileTransferClientView*)pVoid;
	
	// advise main thread that this thread has started
	
	pThis->PostMessage( UWM_GETFILEEVENT, GFE_THREADSTART, 0L );
	
	// create client socket and connect to server

	AfxSocketInit(NULL);	// make certain this is done somewhere in each thread (usually in InitInstance for main thread)
	CSocket sockClient;
	sockClient.Create();
	
	sockClient.Connect( pThis->m_strTargetIP, PRE_AGREED_PORT );	// PRE_AGREED_PORT is #define'd as 8686

	pThis->PostMessage( UWM_GETFILEEVENT, GFE_STATUSCONNECTED, 0L );


	// local variables used in file transfer (declared here to avoid "goto skips definition"-style compiler errors)

	int dataLength, cbBytesRet, cbLeftToReceive;	// used to monitor the progress of a receive operation
	int simulate;		// used to simulate mismatch events (if designated by user)

	BYTE* recdData = NULL;	// pointer to buffer for receiving data (memory is allocated after obtaining file size)

	int pbInterval = 0; int curPB = 0;	// progress bar variables

	CFile destFile;
	CFileException fe;
	BOOL bFileIsOpen = FALSE;
	
	// open/create target file that receives the transferred data

	if( !( bFileIsOpen = destFile.Open( pThis->m_strFileName, 
		CFile::modeCreate | CFile::modeWrite | CFile::typeBinary, &fe ) ) )
	{
		TCHAR strCause[256];
		fe.GetErrorMessage( strCause, 255 );
		TRACE( "GetFileFromRemoteSender encountered an error while opening the local file\n"
			"\tFile name = %s\n\tCause = %s\n\tm_cause = %d\n\tm_IOsError = %d\n",
			fe.m_strFileName, strCause, fe.m_cause, fe.m_lOsError );

		/* you should handle the error here */

		goto PreReturnCleanup;
	}


	// get the file's size first
	
	cbLeftToReceive = sizeof( dataLength );

	// Inject mismatch events (if selected by user)
	// Seed the random-number generator with current time 
	srand( (unsigned)time( NULL ) );

	simulate = 1 + rand() % 2;	// either 1 or 2
	simulate = ( pThis->m_bSimulateEvents ) ? simulate : 0;	// zero if user de-selected event simulation

	do
	{
		BYTE* bp = (BYTE*)(&dataLength) + sizeof(dataLength) - cbLeftToReceive;
		cbBytesRet = sockClient.Receive( bp, cbLeftToReceive - simulate );
		simulate = 0;

		// test for errors and get out if they occurred
		if ( cbBytesRet == SOCKET_ERROR || cbBytesRet == 0 )
		{
			int iErr = ::GetLastError();
			TRACE( "GetFileFromRemoteSite returned a socket error while getting file length\n"
				"\tNumber of Bytes received (zero means connection was closed) = %d\n"
				"\tGetLastError = %d\n", cbBytesRet, iErr );
			
			/* you should handle the error here */
			
			goto PreReturnCleanup;
		}

		// good data was retrieved, so accumulate it with already-received data
		cbLeftToReceive -= cbBytesRet;

	}
	while ( cbLeftToReceive > 0 );

	dataLength = ntohl( dataLength );

	
	// set up progress bar based on expected length of file

	pbInterval = dataLength>>7;		// divide by 128
	curPB = 0;

	pThis->m_ctlProgressGet.PostMessage( PBM_SETPOS, (WPARAM) curPB, 0L );


	// now get the file in RECV_BUFFER_SIZE chunks at a time
	
	recdData = new byte[RECV_BUFFER_SIZE];
	cbLeftToReceive = dataLength;
	
	do
	{	
		int iiGet, iiRecd;

		// simulate mismatch events
		
		simulate = rand();
		simulate = ( simulate>RAND_MAX/10 ) ? 0 : 2560*simulate/RAND_MAX ;	// up to 256 but only inject mismatches 10% of the time
		simulate = ( pThis->m_bSimulateEvents ) ? simulate : 0 ;	// zero if user de-selected event simulation
		
		iiGet = (cbLeftToReceive<RECV_BUFFER_SIZE) ? cbLeftToReceive : RECV_BUFFER_SIZE ;
		iiRecd = sockClient.Receive( recdData, iiGet - simulate );
		simulate = 0;
		
		// test for errors and get out if they occurred
		if ( iiRecd == SOCKET_ERROR || iiRecd == 0 )
		{
			int iErr = ::GetLastError();
			TRACE( "GetFileFromRemoteSite returned a socket error while getting chunked file data\n"
				"\tNumber of Bytes received (zero means connection was closed) = %d\n"
				"\tGetLastError = %d\n", iiRecd, iErr );

			/* you should handle the error here */
			
			goto PreReturnCleanup;
		}

		// good data was retrieved, so accumulate it with already-received data
		// but first, advise main thread of a receive mismatch if we have not yet received everything expected

		if ( iiGet != iiRecd )
		{
			pThis->m_iNumMismatches++;
			pThis->PostMessage( UWM_GETFILEEVENT, GFE_UPDATECONTROLS, 0L );
		}

		destFile.Write( recdData, iiRecd); // Write it
		cbLeftToReceive -= iiRecd;

		// update progress bar

		if ( pbInterval*curPB < (dataLength-cbLeftToReceive) )
		{
			curPB++;
			pThis->m_ctlProgressGet.PostMessage( PBM_SETPOS, (WPARAM) curPB, 0L );
		}

	} 
	while ( cbLeftToReceive > 0 );


	
PreReturnCleanup:		// labelled "goto" destination

	// free allocated memory
	// if we got here from a goto that skipped allocation, delete of NULL pointer
	// is permissible under C++ standard and is harmless
	delete[] recdData;		

	if ( bFileIsOpen )
		destFile.Close();	// only close file if it's open (open might have failed above)

	sockClient.Close();

	pThis->PostMessage( UWM_GETFILEEVENT, GFE_THREADCOMPLETE, 0L );
	
	return 0;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -