📄 client.cpp
字号:
// Client.cpp : implementation file
//
#include "stdafx.h"
#include "CFileClient.h"
#include "Client.h"
#include "CFileClientDlg.h"
#include "Global.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CClient
CClient::CClient()
{
m_pParent = NULL;
m_bCanceled = FALSE;
}
CClient::~CClient()
{
m_listExpectedFiles.RemoveAll();
CleanupAvailableFilesList();
}
// Do not edit the following lines, which are needed by ClassWizard.
#if 0
BEGIN_MESSAGE_MAP(CClient, CSocket)
//{{AFX_MSG_MAP(CClient)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#endif // 0
/////////////////////////////////////////////////////////////////////////////
// CClient member functions
void CClient::OnClose(int nErrorCode)
{
// TODO: Add your specialized code here and/or call the base class
CSocket::OnClose(nErrorCode);
}
void CClient::RequestBrowse()
{
char pBuf[5];
pBuf[0] = (char)(BYTE)TF_BROWSE;
*(int*)(pBuf+1) = (int)0;
Send(pBuf, sizeof(pBuf));
}
void CClient::RequestDownloadNext()
{
if(m_CurFile.posNext == NULL)
{
if(m_listExpectedFiles.GetCount() != 0)//下载文件结束
{
m_listExpectedFiles.RemoveAll();
return;
}
else//文件下载列表为空
return;
}
CString strFileName;
strFileName = m_listExpectedFiles.GetNext(m_CurFile.posNext);
PBYTE pBuf = new BYTE[sizeof(BYTE)+sizeof(int)+sizeof(int)+strFileName.GetLength()*sizeof(TCHAR)];
int nOffset = 0;
*pBuf = (BYTE)TF_DOWNLOAD;
nOffset += sizeof(BYTE);
*(int*)(pBuf+nOffset) = (int)(sizeof(int)+strFileName.GetLength()*sizeof(TCHAR));
nOffset += sizeof(int);
*(int*)(pBuf+nOffset) = strFileName.GetLength();
nOffset += sizeof(int);
memcpy(pBuf+nOffset, strFileName, strFileName.GetLength()*sizeof(TCHAR));
nOffset += strFileName.GetLength()*sizeof(TCHAR);
Send(pBuf, nOffset);
delete []pBuf;
TRACE("RequestNext\n");
}
void CClient::CancelTransfer()
{
TerminateTransfer();
m_listExpectedFiles.RemoveAll();
BYTE pBuf[5] = {0};
pBuf[0] = (BYTE)TF_CANCEL;
*(int*)(pBuf+1) = (int)0;
Send(pBuf, sizeof(pBuf));
m_bCanceled = TRUE;
}
void CClient::OnReceive(int nErrorCode)
{
//接收处理数据
ReceiveData();
CSocket::OnReceive(nErrorCode);
}
void CClient::SetParent(CWnd *pParent)
{
ASSERT(pParent);
m_pParent = pParent;
}
void CClient::OnBrowseFiles()
{
if(!m_listAvailableFiles.IsEmpty())
CleanupAvailableFilesList();
if(m_pParent)
m_pParent->SendMessage(WM_CLIENT_REP, CMD_BROWSE, (LPARAM)RV_CLEAN);
int nCounts = 0;
ExtractCommand(&nCounts, sizeof(int));
PBYTE pBuf = new BYTE[sizeof(DWORD)+sizeof(time_t)];
int nStrLen;
for(int i = 0; i < nCounts; i++)
{
FILE_INFO* pNewInfo = new FILE_INFO;
ASSERT(pNewInfo != NULL);
nStrLen = 0;//in TCHAR
ExtractCommand(&nStrLen, sizeof(int));
ExtractCommand(pNewInfo->strFileName.GetBufferSetLength(nStrLen), nStrLen*sizeof(TCHAR));
pNewInfo->strFileName.ReleaseBuffer(nStrLen);
memset(pBuf, 0, sizeof(DWORD)+sizeof(time_t));
ExtractCommand(pBuf, sizeof(DWORD)+sizeof(time_t));
pNewInfo->dwFileSize = *(DWORD*)pBuf;
pNewInfo->tmFileCreated = CTime(*(time_t*)(pBuf+sizeof(DWORD)));
m_listAvailableFiles.AddTail(pNewInfo);
m_pParent->SendMessage(WM_CLIENT_REP, CMD_BROWSE, (LPARAM)RV_ADD);
}
delete []pBuf;
}
void CClient::OnDownloadFile()
{
int nStrLen = 0;//in TCHAR
ExtractCommand(&nStrLen, sizeof(int));
ExtractCommand(m_CurFile.strFileName.GetBufferSetLength(nStrLen), nStrLen*sizeof(TCHAR));
m_CurFile.strFileName.ReleaseBuffer(nStrLen);
ExtractCommand(&m_CurFile.dwFileLen, sizeof(DWORD));
if(m_CurFile.strFileName.IsEmpty() || m_CurFile.dwFileLen == 0)
{//下载文件失败,可能不存在
m_CurFile.strFileName.Empty();
m_CurFile.dwFileLen = 0;
RequestDownloadNext();//请求下载下一个文件
return;
}
if(m_pParent)
m_CurFile.strFileName = ((CCFileClientDlg*)m_pParent)->m_strDestDir
+ m_CurFile.strFileName;
}
void CClient::OnTransferFile(int nFileDataLen)
{
if(m_CurFile.pFile == NULL)
{
ASSERT(!m_CurFile.strFileName.IsEmpty());
ASSERT(m_CurFile.dwFileLen != 0);
ASSERT(m_CurFile.dwReceivedLen == 0);
m_CurFile.pFile = new CFile;
ASSERT(m_CurFile.pFile);
if(!m_CurFile.pFile->Open(m_CurFile.strFileName,
CFile::modeWrite | CFile::shareExclusive | CFile::modeCreate))
{
TRACE("打开文件错误!");
goto ErrorHandle;
}
m_CurFile.dwReceivedLen = 0;
TRACE("File transfer was begined!\n");
}
ASSERT(m_CurFile.pFile);
ASSERT(m_CurFile.pFile->m_hFile != CFile::hFileNull);
ASSERT(m_CurCmd.nPos+nFileDataLen <= m_CurCmd.nLen);
m_CurFile.pFile->Write(m_CurCmd.pCmd+m_CurCmd.nPos, nFileDataLen);
m_CurCmd.nPos += nFileDataLen;
m_CurFile.dwReceivedLen += nFileDataLen;
TransferResponse((BYTE)TF_OK);
if(m_CurFile.dwReceivedLen == m_CurFile.dwFileLen)
{
TerminateTransfer();
TRACE("Transfer file was finished!\n");
RequestDownloadNext();
}
return;
ErrorHandle:
TransferResponse((BYTE)TF_ERROR);
TRACE("Transfer file was terminated for some error!\n");
TerminateTransfer();
AfxThrowUserException();
}
void CClient::TransferResponse(BYTE nErrorFlag)
{
BYTE pBuf[6];
pBuf[0] = (BYTE)TF_FILE;
*(int*)(pBuf+1) = (int)1;
pBuf[5] = nErrorFlag;
Send(pBuf, sizeof(pBuf));
}
void CClient::ReceiveData()
{
/*
BYTE nFlag;
Receive(&nFlag, 1);
if(nFlag == (BYTE)TF_FILE)
{
int nRead = 0, nLeft = 32*1024, nBytes = 0;
while(nLeft > 0)
{
nBytes = Receive(pData, nLeft);
if(nBytes == SOCKET_ERROR)
ASSERT(FALSE);
else
{
nRead += nBytes;
nLeft -= nBytes;
}
}
static int nCount = 0;
TRACE("%d Packages Received\n", ++nCount);
Send(&nFlag, 1);
}
else
ASSERT(FALSE);
*/
/*
BYTE nFlag;
*this >> nFlag;
if(nFlag == (BYTE)TF_FILE)
{
if(Read(pData, 32*1024) < 32*1024)
ASSERT(FALSE);
static int nCount = 0;
TRACE("%d Packages Received\n", ++nCount);
*this << nFlag;
Flush();
}
else
ASSERT(FALSE);
*/
/*
DWORD dwPending = 0;
if(!IOCtl(FIONREAD, &dwPending) || dwPending < 5)//网络上数据数小于5,暂不接收
return;
*/
int nRead = 0;
nRead = CAsyncSocket::Receive(m_Data.pBuf+m_Data.nLeft, m_Data.MAX_BUF_LEN-m_Data.nLeft);
if(nRead <= 0)
return;
m_Data.nLeft += nRead; //缓冲区剩余可用数据
int nPos = 0;
while(nPos < m_Data.nLeft && (m_CurCmd.nPos != 0 || m_Data.nLeft-nPos >= 5))//如是新命令,则至少包含一个标志位与数据包长度
{
if(m_CurCmd.nPos == 0)//新命令
m_CurCmd.ResetBufLen(*(int*)(m_Data.pBuf+nPos+1)+5);
int nCopied = min(m_CurCmd.nLen-m_CurCmd.nPos, m_Data.nLeft-nPos);
memcpy(m_CurCmd.pCmd+m_CurCmd.nPos, m_Data.pBuf+nPos, nCopied);
nPos += nCopied;
m_CurCmd.nPos += nCopied;
if(m_CurCmd.nPos == m_CurCmd.nLen)//收到完整命令,开始处理命令
{
//Handle Command
HandleCommand();
//Reset Command Buffer
m_CurCmd.ResetBufLen(0);
}
}
if(nPos < m_Data.nLeft)//接收缓冲区中尚有数据未处理
{
memmove(m_Data.pBuf, m_Data.pBuf+nPos, m_Data.nLeft-nPos);
m_Data.nLeft -= nPos;
}
else
m_Data.nLeft = 0;
/*
if(m_CurFile.dwReceivedLen < m_CurFile.dwPackEndLen)//当前数据包未收完整
{
OnTransferFile();
}
else
{
BYTE byteFlag;
Receive(&byteFlag, sizeof(BYTE));
switch(byteFlag)
{
case TF_BROWSE:
OnBrowseFiles();
break;
case TF_DOWNLOAD:
OnDownloadFile();
break;
case TF_FILE:
OnTransferFile();
break;
case TF_CHECKSERVER:
break;
default:
break;
}
}
*/
}
void CClient::TerminateTransfer()
{
if(m_CurFile.pFile && m_CurFile.pFile->m_hFile != CFile::hFileNull)
m_CurFile.pFile->Close();
if(m_CurFile.pFile)
{
delete m_CurFile.pFile;
m_CurFile.pFile = NULL;
}
m_CurFile.strFileName.Empty();
m_CurFile.dwFileLen = 0;
m_CurFile.dwReceivedLen = 0;
}
BOOL CClient::AttemptToConnect(CString strIP, UINT uPort)
{
ASSERT(m_hSocket == INVALID_SOCKET);
BOOL bRes = TRUE;
if(strIP.IsEmpty() || !Create() || !Connect(strIP, uPort))
{
if(m_hSocket != INVALID_SOCKET)
Close();
ASSERT(m_hSocket == INVALID_SOCKET);
bRes = FALSE;
}
CleanupAvailableFilesList();
m_pParent->PostMessage(WM_CLIENT_REP, (WPARAM)CMD_CONNECT, (LPARAM)bRes);
return bRes;
}
void CClient::AttemptToDisconnect()
{
if(m_hSocket == INVALID_SOCKET)
return;
ShutDown(CSocket::both);
Close();
ASSERT(m_hSocket == INVALID_SOCKET);
m_pParent->PostMessage(WM_CLIENT_REP, (WPARAM)CMD_DISCONNECT, (LPARAM)FALSE);
}
void CClient::CleanupAvailableFilesList()
{
if(m_listAvailableFiles.IsEmpty())
return;
POSITION pos = m_listAvailableFiles.GetHeadPosition();
while(pos)
{
FILE_INFO*& pInfo = (FILE_INFO*&)m_listAvailableFiles.GetNext(pos);
if(pInfo)
{
delete pInfo;
pInfo = NULL;
}
}
m_listAvailableFiles.RemoveAll();
}
BOOL CClient::InitDownload()
{
m_CurFile.posNext = m_listExpectedFiles.GetHeadPosition();
return (m_CurFile.posNext != NULL);
}
void CClient::HandleCommand()
{
ASSERT(m_CurCmd.pCmd);
ASSERT(m_CurCmd.nLen >= 5);
m_CurCmd.nPos = 0;//重置位置指针
BYTE nFlag = 0;
int nPackLen = 0;
ExtractCommand(&nFlag, sizeof(BYTE));
ExtractCommand(&nPackLen, sizeof(int));
switch(nFlag)
{
case TF_BROWSE:
OnBrowseFiles();
break;
case TF_DOWNLOAD:
OnDownloadFile();
break;
case TF_FILE:
if(!m_bCanceled)
OnTransferFile(nPackLen);
break;
case TF_CANCEL:
m_bCanceled = FALSE;
break;
case TF_CHECKSERVER:
break;
default:
break;
}
}
int CClient::ExtractCommand(void* pData, int nLen)
{
ASSERT(pData);
ASSERT(AfxIsValidAddress(pData, nLen));
ASSERT(m_CurCmd.nPos+nLen <= m_CurCmd.nLen);
memcpy(pData, m_CurCmd.pCmd+m_CurCmd.nPos, nLen);
m_CurCmd.nPos += nLen;
return nLen;
}
void CClient::CloseSocket()
{
if(m_hSocket == INVALID_SOCKET)
return;
ShutDown(both);
Close();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -