下面是一段从server端向client端发送文件的代码:
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;
}
1:其中的simulate实现了什么功能?
2:在第一个do while循环中完成了什么功能?BYTE* bp = (BYTE*)(&fileLength) + sizeof(fileLength) - cbLeftToSend; 是什么意思?我感觉第一个do while 应该是完成文件大小的传递,是不是呢?
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;
}
1:其中的simulate实现了什么功能?
2:在第一个do while循环中完成了什么功能?BYTE* bp = (BYTE*)(&fileLength) + sizeof(fileLength) - cbLeftToSend; 是什么意思?我感觉第一个do while 应该是完成文件大小的传递,是不是呢?
解决方案 »
免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货