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

📄 p2p.cpp

📁 类似于QQ的聊天工具,分为客户端和服务器端,有共享空间,能发布公告,可传输文件
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// P2P.cpp: implementation of the CP2P class.
//
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// 功能:			文件传输类/ 客户端之间
// 日期:			2005-12-10
// 最后更新:		2005-12-18
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "NetQQ.h"
#include "P2P.h"
#include "ChatDlg.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CP2P::CP2P()
{
	m_bFileLinstenStatus = false;
	m_Port               = 0;
	m_ftParam            = NULL;
	m_hdlFT              = NULL;
}

CP2P::~CP2P()
{
	closesocket(m_FileListenSocket);
	WSACleanup();
}


/////////////////////////////////////////////////////////////////////////////
//初始化文件传输套接字并开始监听
void CP2P::InitFlieListenSock()
{
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	
	wVersionRequested = MAKEWORD(1, 1);
	
	err = WSAStartup(wVersionRequested, &wsaData);
	if ( err != 0 ) 
	{
		return;
	}
	
	if ( LOBYTE( wsaData.wVersion ) != 1 ||
        HIBYTE( wsaData.wVersion ) != 1 ) 
	{
		WSACleanup();
		return; 
	}

	//////////////////////////////////////////////////////////////
	//创建文件传输socket
	m_FileListenSocket = socket(AF_INET, SOCK_STREAM,IPPROTO_IP);
	
	SOCKADDR_IN addr;
	addr.sin_family           = AF_INET;
	addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	addr.sin_port             = htons(0);
	
	int nSize = sizeof(addr);
	///////////////////////////////////////////////////////////////////////
	// 绑定套接字到本地IP和随即端口
	if (SOCKET_ERROR == bind(m_FileListenSocket, (sockaddr*)&addr, nSize))
	{
		int i = WSAGetLastError();
		AfxMessageBox("绑定本地文件传输套接字到端口失败!");
		WSACleanup();
		return;
	}
	// 监听所绑定的套接字端口
	if (SOCKET_ERROR == listen(m_FileListenSocket, 5))
	{
		int i = WSAGetLastError();
		AfxMessageBox("监听本地文件传输套接字失败!");	
		WSACleanup();
		return;
	}
	// 获取由系统所分配的端口号
	int nret = getsockname(m_FileListenSocket, (SOCKADDR*)&addr, &nSize);
	if(nret)
	{
		CString tmp;
		tmp.Format("获取由系统所分配的端口号 出错!错误号:%d。",nret);
		AfxMessageBox(tmp);	
		WSACleanup();
		return;
	}

	// 将网络续转换并放到成员变量中
	m_Port = ntohs(addr.sin_port);
	m_bFileLinstenStatus = true;
}


/////////////////////////////////////////////////////////////////////////////
//开启接收文件线程
void CP2P::OnAccept(CWnd* pWnd)
{
	// 获取客户端以及连接用套接字
	SOCKADDR_IN client;
	int sClientLength = sizeof(client);
	SOCKET s = accept(m_FileListenSocket, (sockaddr*)&client, &sClientLength);

	// 定义接收和分解文件发送端发送的文件信息数据变量
	CString strFileInfo,strRecv;
	char buf[10240]="\0";

	int nGet = 0;
	do
	{
		nGet = recv(s, buf, sizeof(buf), MSG_PARTIAL);
	}
	while(nGet<1);//接收到不为空的

	CString strArray[4];
	CMsgBag mbTool;
	tagPacketParam pp;

	//判断接收到的是否跟打包的数据长度相等
	int tmpn = mbTool.GetPacketLen(CString(buf)) + 4;
	if (nGet != tmpn)
	{
		closesocket(s);
		AfxMessageBox("接收到的文件信息缓存为空!");
		return;
	}

	// 相等再拆包
	mbTool.SplitDate(CString(buf), strArray);
	
	DWORD exitCode = 0;
    GetExitCodeThread(m_hdlFT,&exitCode);
    if(exitCode == STILL_ACTIVE)
	{
		send(s, "NO", 2, MSG_PARTIAL);
		closesocket(s);
		return;
	}

	// 生成显示给用户的文件信息
	//CString msg = "是否接收文件:"+ strArray[0]+"\n"+strArray[1]+"\n"+strArray[2]+"\n"+strArray[3];
	CMainDlg* pMianWnd = (CMainDlg*)pWnd;
	CChatDlg* pChatDlg = (CChatDlg*)pMianWnd->CreateChatWindow(strArray[0]);

	CString strInfo = "文件传输请求,请单击右边的[是]或[否]接受或拒绝请求\r\n文件名:" 
						+ strArray[1] + "  大小:" + strArray[2];
	pChatDlg->ShowFileTransferInfo(strInfo);

	// 设置文件接收线程参数
	m_ftParam                = new _ThreadParam;
	m_ftParam->m_pWnd        = pChatDlg;
	m_ftParam->m_sSock       = s;
	m_ftParam->m_strFileName = buf;

	m_hdlFT = CreateThread(NULL, 0, AcceptFunc, (LPVOID)m_ftParam, 0, NULL);
}

/////////////////////////////////////////////////////////////////////////////
//文件接收处理线程
DWORD WINAPI CP2P::AcceptFunc(LPVOID lpParam)
{
	// 接收参数
	_ThreadParam* lp = (_ThreadParam*)lpParam;	
	CChatDlg* pDlg   = (CChatDlg*)(lp->m_pWnd);
	SOCKET s         = lp->m_sSock;
	CString strBuf   = lp->m_strFileName;
	
	//等待用户接受或拒绝文件传输回应
	WaitForSingleObject(pDlg->GetMutex(), 30000);

	//获取用户回应
	UINT ret = pDlg->GetFileTransferChoose();
	//拒绝接受
	if(ret != faqYes)
	{
		if(ret == faqInit)
		{
			send(s, "OUT", 3, MSG_PARTIAL);
			ReleaseMutex(pDlg->GetMutex());
			pDlg->SetMutexNull();
			CString msg = "等待超时,系统取消了文件传输回复请求...";
			pDlg->ShowFileTransferInfo(msg);
			pDlg->GetDlgItem(IDC_BTN_FYES)->ShowWindow(false);
			pDlg->GetDlgItem(IDC_BTN_FNO)->ShowWindow(false);
		}
		pDlg->InitFileAcceptQuery();
		closesocket(s);
		delete lp; lp = NULL;
		return 0;
	}
	pDlg->InitFileAcceptQuery();
	pDlg->GetDlgItem(IDC_BTN_CANCLE)->ShowWindow(true);

	////////////////////////////////////////////////////////////////////////
	//获取接收文件信息
	CString strArray[4];
	CMsgBag mbTool;
	mbTool.SplitDate(strBuf, strArray);

	// 选择存放地址
	CFileDialog fdlg(FALSE, NULL, strArray[1],
		OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "所有文件(*.*)|*.*||");
	if(fdlg.DoModal() == IDCANCEL)
	{
		closesocket(s);
		pDlg->GetDlgItem(IDC_BTN_CANCLE)->ShowWindow(false);
		delete lp; lp = NULL;
		return 0;
	}		

	// 返回接收回复
	send(s, "T", 1, MSG_PARTIAL);

	///////////////////////////////////////////////////////////////////////
	//开始接收文件
	CFile file;
	CFileException e;
	if(!file.Open(fdlg.GetPathName(), CFile::modeReadWrite|CFile::modeCreate
												|CFile::shareDenyWrite, &e))
	{
		char err[128];
		closesocket(s);
		e.GetErrorMessage(err, 128);	
		pDlg->InsertNewChatInfo("文件打开失败:" + CString(err));
		pDlg->GetDlgItem(IDC_BTN_CANCLE)->ShowWindow(false);
		delete lp; lp = NULL;
		return 3;
	}
	lp->m_pFile = &file;

	pDlg->GetDlgItem(IDC_STCT0)->SetWindowText(file.GetFileName());
	pDlg->GetDlgItem(IDC_STCT1)->SetWindowText("大小:" + strArray[2]);
	
	CProgressCtrl* fprog = (CProgressCtrl*)pDlg->GetDlgItem(IDC_PRGR);
	fprog->SetRange(0, 1000);
	fprog->SetStep(1);
	fprog->SetPos(0);
	fprog->ShowWindow(true);

	char buf[10240]="\0";
	BOOL bRead = TRUE;
	int  nRecieve = 0;
	char strSized[10] = "", strPecent[10] = "";
	while(bRead)
	{
		int nResult = recv(s, buf, sizeof(buf), MSG_PARTIAL);

		switch(nResult)
		{
			case 0:
			{
				bRead = FALSE;
				break;
			}

			case SOCKET_ERROR:
			{
				if (GetLastError() != WSAEWOULDBLOCK) 
				{
					bRead = FALSE;
				}
				break;
			}
			default:
				file.Write(buf, nResult);
				nRecieve += nResult;

⌨️ 快捷键说明

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