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

📄 client.cpp

📁 一个关于下载文件客户程序的小程序
💻 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 + -