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

📄 filetransferserverview.cpp

📁 vc++网络程序设计实例详解 人民邮电出版社1-2章源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	
	BYTE* sendData = NULL;			// pointer to buffer for sending data (memory is allocated after sending file size)
	
	CFile sourceFile;
	CFileException fe;
	BOOL bFileIsOpen = FALSE;
	
	if( !( bFileIsOpen = sourceFile.Open( fName, CFile::modeRead | CFile::typeBinary, &fe ) ) )
	{
		TCHAR strCause[256];
		fe.GetErrorMessage( strCause, 255 );
		TRACE( "SendFileToRemoteRecipient 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;
	}
	

	// first send length of file
	
	fileLength = sourceFile.GetLength();
	fileLength = htonl( fileLength );
	
	cbLeftToSend = sizeof( fileLength );
	
	do
	{
		int cbBytesSent;
		BYTE* bp = (BYTE*)(&fileLength) + sizeof(fileLength) - cbLeftToSend;
		cbBytesSent = sockConnection.Send( bp, cbLeftToSend );
		
		// test for errors and get out if they occurred
		if ( cbBytesSent == SOCKET_ERROR )
		{
			int iErr = ::GetLastError();
			TRACE( "SendFileToRemoteRecipient returned a socket error while sending file length\n"
				"\tNumber of Bytes sent = %d\n"
				"\tGetLastError = %d\n", cbBytesSent, iErr );
			
			/* you should handle the error here */

			bRet = FALSE;
			goto PreReturnCleanup;
		}
		
		// data was successfully sent, so account for it with already-sent data
		cbLeftToSend -= cbBytesSent;
	}
	while ( cbLeftToSend>0 );
	
	
	// now send the file's data
	
	sendData = new BYTE[SEND_BUFFER_SIZE]; 
	
	cbLeftToSend = sourceFile.GetLength();
	
	do
	{
		// read next chunk of SEND_BUFFER_SIZE bytes from file
		
		int sendThisTime, doneSoFar, buffOffset;
		
		sendThisTime = sourceFile.Read( sendData, SEND_BUFFER_SIZE );
		buffOffset = 0;
		
		do
		{
			doneSoFar = sockConnection.Send( sendData + buffOffset, sendThisTime ); 
			
			// test for errors and get out if they occurred
			if ( doneSoFar == SOCKET_ERROR )
			{
				int iErr = ::GetLastError();
				TRACE( "SendFileToRemoteRecipient returned a socket error while sending chunked file data\n"
					"\tNumber of Bytes sent = %d\n"
					"\tGetLastError = %d\n", doneSoFar, 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 send fewer bytes than requested
			  
			if ( doneSoFar != sendThisTime )
			{
				int ii = 0;
			}
****************************/
			
			// data was successfully sent, so account for it with already-sent data
			
			buffOffset += doneSoFar;
			sendThisTime -= doneSoFar;
			cbLeftToSend -= doneSoFar;
		}
		while ( sendThisTime > 0 );
		
	}
	while ( cbLeftToSend > 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[] sendData;
	
	if ( bFileIsOpen )
		sourceFile.Close();		// only close file if it's open (open might have failed above)
	
	sockConnection.Close();
	
	return bRet;
	
}


UINT CFileTransferServerView::ThreadedSendFileToRemoteRecipient(LPVOID pVoid)
{
	CFileTransferServerView* pThis = (CFileTransferServerView*)pVoid;
	pThis->PostMessage( UWM_FILESENDEVENT, FSE_THREADSTART, 0L );
	
	AfxSocketInit(NULL);	// make certain this is done somewhere in each thread (usually in InitInstance for main thread)
	CSocket sockSrvr; 
	sockSrvr.Create(PRE_AGREED_PORT); // Creates our server socket
	sockSrvr.Listen(); // Start listening for the client at PORT
	CSocket sockConnection;
	sockSrvr.Accept(sockConnection); // Use another CSocket to accept the connection
	
	pThis->PostMessage( UWM_FILESENDEVENT, FSE_STATUSCONNECTED, 0L );
	
	// local variables used in file transfer (declared here to avoid "goto skips definition"-style compiler errors)

	int fileLength, cbLeftToSend;	// used to monitor the progress of a sending operation
	int simulate;	// used to simulate mismatch events (if designated by user)
	
	BYTE* sendData = NULL;	// pointer to buffer for sending data (memory is allocated after sending file size)
	
	int pbInterval = 0; int curPB = 0;	// progress bar variables
	
	
	CFile sourceFile;
	CFileException fe;
	BOOL bFileIsOpen = FALSE;
	
	if( !( bFileIsOpen = sourceFile.Open( pThis->m_strFileName, CFile::modeRead | CFile::typeBinary, &fe ) ) )
	{
		TCHAR strCause[256];
		fe.GetErrorMessage( strCause, 255 );
		TRACE( "SendFileToRemoteRecipient 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;
	}

	
	
	// first send length of file
	
	fileLength = sourceFile.GetLength();
	fileLength = htonl( fileLength );
	
	cbLeftToSend = sizeof( fileLength );
	
	// 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
	{
		int cbBytesSent;
		BYTE* bp = (BYTE*)(&fileLength) + sizeof(fileLength) - cbLeftToSend;
		cbBytesSent = sockConnection.Send( bp, cbLeftToSend - simulate );
		simulate = 0;
		
		// test for errors and get out if they occurred
		if ( cbBytesSent == SOCKET_ERROR )
		{
			int iErr = ::GetLastError();
			TRACE( "SendFileToRemoteRecipient returned a socket error while sending file length\n"
				"\tNumber of Bytes sent = %d\n"
				"\tGetLastError = %d\n", cbBytesSent, iErr );
			
			/* you should handle the error here */
			
			goto PreReturnCleanup;
		}
		
		// data was successfully sent, so account for it with already-sent data
		cbLeftToSend -= cbBytesSent;
	}
	while ( cbLeftToSend>0 );
	
	
	// now send the file's data
	
	sendData = new BYTE[SEND_BUFFER_SIZE]; 
	
	cbLeftToSend = sourceFile.GetLength();
	
	
	// set up progress bar
	
	fileLength = cbLeftToSend;
	pbInterval = fileLength>>7;		// divide by 128
	curPB = 0;
	
	pThis->m_ctlProgressSend.PostMessage( PBM_SETPOS, (WPARAM) curPB, 0L );
	
	do
	{
		// read next chunk of SEND_BUFFER_SIZE bytes from file
	
		int sendThisTime, doneSoFar, buffOffset;
		
		sendThisTime = sourceFile.Read( sendData, SEND_BUFFER_SIZE );
		buffOffset = 0;
		
		// 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
		
		do
		{
			doneSoFar = sockConnection.Send( sendData + buffOffset, sendThisTime - simulate ); 
			simulate = 0;
			
			// test for errors and get out if they occurred
			if ( doneSoFar == SOCKET_ERROR )
			{
				int iErr = ::GetLastError();
				TRACE( "SendFileToRemoteRecipient returned a socket error while sending chunked file data\n"
					"\tNumber of Bytes sent = %d\n"
					"\tGetLastError = %d\n", doneSoFar, iErr );
				
				/* you should handle the error here */
				
				goto PreReturnCleanup;
			}
			
			// data was successfully sent, so account for it with already-sent data
			// but first, advise main thread of a send mismatch if everything was not sent in one shot
			
			if ( doneSoFar != sendThisTime )
			{
				pThis->m_iNumMismatches++;
				pThis->PostMessage( UWM_FILESENDEVENT, FSE_UPDATECONTROLS, 0L );
			}
			
			buffOffset += doneSoFar;
			sendThisTime -= doneSoFar;
			cbLeftToSend -= doneSoFar;
		}
		while ( sendThisTime > 0 );
		
		// update progress bar
		
		if ( pbInterval*curPB < (fileLength-cbLeftToSend) )
		{
			curPB++;
			pThis->m_ctlProgressSend.PostMessage( PBM_SETPOS, (WPARAM) curPB, 0L );
		}
		
	}
	while ( cbLeftToSend > 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[] sendData;
	
	if ( bFileIsOpen )
		sourceFile.Close();		// only close file if it's open (open might have failed above)
	
	sockConnection.Close();
	
	// advise main thread that we're completed
	pThis->PostMessage( UWM_FILESENDEVENT, FSE_THREADCOMPLETE, 0L );
	
	return 0;
	
}

⌨️ 快捷键说明

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