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

📄 filetransfer.cpp

📁 带文件传输功能的聊天室,可多人聊天,也可私聊,任意用户间可互传文件
💻 CPP
字号:
// FileTransfer.cpp: implementation of the CFileTransfer class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "chatter.h"
#include "chattermgr.h"
#include "FileTransfer.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif



//监听文件传送线程
UINT AcceptFunc( LPVOID pParam )
{
	SOCKET s = (SOCKET)pParam;
	
	listen(s, 5);
	sockaddr_in client;
	int sClientLength = sizeof(client);
	while(true)
	{
		SOCKET sClient = accept(s,  (sockaddr*)&client, &sClientLength);
		
		AfxBeginThread(ReceiveFunc, (LPVOID)sClient);
	}
	
}

//连接另外用户,传送文件
UINT ConnectFunc( LPVOID pParam )
{
	//取得用户信息
	LPFILETRANSFER lpF = (LPFILETRANSFER)pParam;
	LPUSERINFO lpUser = lpF->m_lpUser;

	SOCKET s = socket(AF_INET, SOCK_STREAM,IPPROTO_IP);
	SOCKADDR_IN sockAddr;
	memset(&sockAddr,0,sizeof(sockAddr));
	
	sockAddr.sin_family = AF_INET;
	sockAddr.sin_addr.s_addr = inet_addr(lpUser->m_ip);
	sockAddr.sin_port = htons((u_short)lpUser->m_nFilePort);

	//打开文件
	CFile file;
	CFileException e;
	if(!file.Open(lpF->m_fileName, CFile::modeRead | CFile::typeBinary, &e))
	{
		char szError[1024];
		e.GetErrorMessage(szError, 1024);	
		GetChatterMgr()->DoServerMessage("文件打开失败:"+CString(szError));
		
		closesocket(s);
		delete lpF;
		return 0;
	}

	//连接用户
	if(SOCKET_ERROR  == connect(s, (sockaddr*)&sockAddr, sizeof(sockAddr)))
	{
		GetChatterMgr()->DoServerMessage("连接失败,请确认 ["+CString(lpUser->m_name)+"] 有无真实IP!");
		closesocket(s);
		delete lpF;
		return 0;
	}
		
	DWORD nFileLength = file.GetLength();

	//发送的数据:文件长度[4个字节]+文件名长度[4个字节]+文件名+用户名长度[4个字节]+用户名称
	
	//获得文件信息
	char buf[1024]="\0";

	//发送的数据
	int nPointer = 0;
	int nSize = sizeof(int);

	//文件长度
	memcpy(buf+nPointer, &nFileLength, nSize);
	nPointer += nSize;
	
	//文件名长度
	int nTmpLength = file.GetFileName().GetLength(); 
	memcpy(buf+nPointer, &nTmpLength, nSize);
	nPointer += nSize;

	//文件名
	sprintf(buf+nPointer, "%s", file.GetFileName());
	nPointer += file.GetFileName().GetLength();

	//用户名长度
	nTmpLength = strlen(GetChatterMgr()->GetUser()->m_name); 
	memcpy(buf+nPointer, &nTmpLength, nSize);
	nPointer +=	nSize;

	//用户名
	sprintf(buf+nPointer, "%s", GetChatterMgr()->GetUser()->m_name);
	nPointer += strlen(GetChatterMgr()->GetUser()->m_name);
	
	if(SOCKET_ERROR  == send(s, buf, nPointer, MSG_PARTIAL))
	{
		GetChatterMgr()->DoServerMessage("异常原因导致传送文件==> ["+CString(lpUser->m_name)+"]失败!");
		closesocket(s);
		delete lpF;
		return 0;		
	}

	//获得接收或拒绝通知
	if( 1 != recv(s, buf, 1, MSG_PARTIAL))
	{
		GetChatterMgr()->DoServerMessage("["+CString(lpUser->m_name)+"] 拒绝接收文件!");
		closesocket(s);
		delete lpF;
		return 0;		
	}

	//添加进度条
	CString szNotify;
	szNotify = "发送文件 ["+CString(file.GetFileName())+"] ";
	DWORD nIndex = GetChatterMgr()->AddTP(szNotify, nFileLength);
	
	GetChatterMgr()->DoServerMessage("["+CString(lpUser->m_name)+"] 同意接收文件,正在传输文件...");

	DWORD nPos = 0;
	DWORD nTime = GetTickCount();
	DWORD nTimeStart = nTime;
	do 
	{
		UINT nBytesRead = file.Read(buf, sizeof(buf));	
		if(SOCKET_ERROR  == send(s, buf, nBytesRead, MSG_PARTIAL))
		{
			GetChatterMgr()->DoServerMessage("异常原因导致传送文件==> ["+CString(lpUser->m_name)+"]失败!");
			closesocket(s);
			delete lpF;
			return 0;		
		}
		nPos+=nBytesRead;
		DWORD nTimeEnd = GetTickCount();
		if(nTimeEnd - nTimeStart > 1000)
		{
			GetChatterMgr()->SetTPStep(nIndex, nPos);

			DWORD nVelocity = nPos/(nTimeEnd-nTime)*1000/1024;
			GetChatterMgr()->SetTPVelocity(nIndex, nVelocity);

			nTimeStart = nTimeEnd;
		}
		if(nBytesRead < sizeof(buf))
			break;

//		Sleep(2);
	} while(TRUE);
	

	file.Close();
	delete lpF;

	closesocket(s);

	GetChatterMgr()->DoServerMessage("传送文件==> ["+CString(lpUser->m_name)+"] 成功");
	
	GetChatterMgr()->DeleteTP(nIndex);
	return 0;
	
}
UINT ReceiveFunc( LPVOID pParam )
{
	SOCKET s = (SOCKET)pParam;

	//接收的数据:文件长度[4个字节]+文件名长度[4个字节]+文件名+用户名长度[4个字节]+用户名称
	
	char buf[1024]="\0";
	char fileName[256]="\0";
	char userName[20]="\0";
	int nLength = 1;
	int nFileLength = 1;
	int nNameLength = 1;

	//文件长度
	int nSize = sizeof(int);
	recv(s, buf, nSize, MSG_PARTIAL);
	memcpy(&nFileLength, buf, nSize);
	
	//文件名长度
	recv(s, buf, nSize, MSG_PARTIAL);
	memcpy(&nLength, buf, nSize);

	//文件名称
	recv(s, fileName, nLength, MSG_PARTIAL);

	//用户名长度
	recv(s, buf, nSize, MSG_PARTIAL);
	memcpy(&nNameLength, buf, nSize);

	//获得用户名称
	recv(s, userName, nNameLength, MSG_PARTIAL);

	CString szNotify;
	szNotify = "["+CString(userName)+"] 传送文件 ["+CString(fileName)+"] ,接收 或 拒绝?";
	
	GetChatterMgr()->DoServerMessage(szNotify);	

	if(AfxMessageBox(szNotify, MB_YESNO) == IDNO)
	{
		closesocket(s);		
		return 0 ;
	}

	CFileDialog fdlg(FALSE,NULL, fileName);
	if(fdlg.DoModal() == IDCANCEL)
	{
		closesocket(s);		
		return 0;
	}		

	//发送接收通知
	send(s, "T", 1, MSG_PARTIAL);

	GetChatterMgr()->DoServerMessage("["+CString(fileName)+"] 传输中....");	
	
	CFile file;
	file.Open(fdlg.GetPathName(), CFile::modeReadWrite|CFile::modeCreate|CFile::shareDenyWrite);

	//添加进度条
	szNotify="接收文件 ["+file.GetFileName()+"]";
	DWORD nIndex = GetChatterMgr()->AddTP(szNotify, nFileLength);
	
	BOOL bRead = TRUE;
	DWORD nPos = 0;
	DWORD nTime = GetTickCount();
	DWORD nTimeStart = nTime;

	while(bRead)
	{
		int nResult = recv(s, buf, 1024, MSG_PARTIAL);
		
		switch(nResult)
		{
		case 0:
			bRead = FALSE;
			break;
		case SOCKET_ERROR:
			if (GetLastError() != WSAEWOULDBLOCK) 
			{
				PRINTDEBUG(FALSE);
				bRead = FALSE;
			}
			else
			{
				break;
			}
		default:
			file.Write(buf, nResult);
		}

		nPos += nResult;
		DWORD nTimeEnd = GetTickCount();
		if(nTimeEnd - nTimeStart > 1000)
		{
			GetChatterMgr()->SetTPStep(nIndex, nPos);

			DWORD nVelocity = nPos/(nTimeEnd-nTime)*1000/1024;
			GetChatterMgr()->SetTPVelocity(nIndex, nVelocity);
			
			nTimeStart = nTimeEnd;
		}
	}
	file.Close();

	closesocket(s);

	GetChatterMgr()->DoServerMessage("["+CString(userName)+"] 传送文件成功 "+fdlg.GetPathName());
	GetChatterMgr()->DeleteTP(nIndex);
	
	return 0;
}

⌨️ 快捷键说明

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