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

📄 p2p.cpp

📁 类似于QQ的聊天工具,分为客户端和服务器端,有共享空间,能发布公告,可传输文件
💻 CPP
📖 第 1 页 / 共 2 页
字号:

				//////////////////////////////////////////////////////////////
				//计算已传输大小及完成百分比
				float mSized = (float)nRecieve / 1024 / 1024;
				sprintf(strSized, "%0.1fM", mSized);

				float mSize = (float)atof(strArray[2].GetBuffer(0));
				sprintf(strPecent, "%0.1f%", (mSized / mSize ) * 100);

				pDlg->GetDlgItem(IDC_STCT2)->SetWindowText(strSized);
				pDlg->GetDlgItem(IDC_STCT3)->SetWindowText(strPecent);
				
				///////////////////////////////////////////////////////////////
				//设置进度条
				int nStep = (int)((mSized / mSize) * 1000);
				fprog->SetPos(nStep);
		}
	}
	file.Close();
	closesocket(s);
	if((nRecieve / 1024 / 1024) < (atoi(strArray[2]) - 0.02))
	{
		pDlg->InsertNewChatInfo("对方中断了文件 [" + strArray[1] + "] 传输!");
	}
	else
	{
		pDlg->InsertNewChatInfo("文件 [" + strArray[1] + "] 传送成功!\r\n保存在:"
			                    + fdlg.GetPathName());
	}

	pDlg->GetDlgItem(IDC_STCT0)->SetWindowText("");
	pDlg->GetDlgItem(IDC_STCT1)->SetWindowText("");
	pDlg->GetDlgItem(IDC_STCT2)->SetWindowText("");
	pDlg->GetDlgItem(IDC_STCT3)->SetWindowText("");
	fprog->ShowWindow(false);
	pDlg->GetDlgItem(IDC_BTN_CANCLE)->ShowWindow(false);

	delete lp; lp = NULL;
	return 0;
}

/////////////////////////////////////////////////////////////////////////////
//文件发送
void CP2P::Filesend(CWnd* pWnd, CString strMyId) 
{
	// 获得文件全名
	CFileDialog fdlg(true, NULL, NULL, 
		OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "所有文件(*.*)|*.*||");
	if(fdlg.DoModal() == IDCANCEL)
	{
		return;
	}
	CString strFile = fdlg.GetPathName();

	// 设置文件传输线程参数
	m_ftParam = new _ThreadParam;
	
	m_ftParam->m_strFileName = strFile;
	m_ftParam->m_strMyId     = strMyId;
	m_ftParam->m_pWnd        = pWnd;

	// 开启发送文件传输线程
	m_hdlFT = CreateThread(NULL, 0, ConnectFunc, (LPVOID)m_ftParam, 0, NULL);	
}

/////////////////////////////////////////////////////////////////////////////
//发送文件传输处理线程
DWORD WINAPI CP2P::ConnectFunc(LPVOID lpParam)
{
	// 接收参数
	_ThreadParam* lp = (_ThreadParam*)lpParam;	
	CChatDlg* pDlg   = (CChatDlg*)(lp->m_pWnd);

	// 定义连接变量
	DWORD dwIp   = inet_addr(pDlg->m_pUserNode->m_strIp.GetBuffer(0));
	short snPort = atoi(pDlg->m_pUserNode->m_strFilePort);
	SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
	SOCKADDR_IN addrSend;
	addrSend.sin_family           = AF_INET;
	addrSend.sin_addr.S_un.S_addr = dwIp;
	addrSend.sin_port             = htons(snPort);

	// 连接接收端
	int ret = connect(s, (SOCKADDR*)&addrSend, sizeof(SOCKADDR));
	if(SOCKET_ERROR  == ret)
	{
		closesocket(s);
		pDlg->InsertNewChatInfo("无法连接对方用于文件传输!");
		delete lp; lp = NULL;
		return 1;
	}
	lp->m_sSock = s;

	// 建立连接后打开文件
	CFile file;
	CFileException e;
	if(!file.Open(lp->m_strFileName, CFile::modeRead | CFile::shareDenyNone | CFile::typeBinary, &e))
	{
		closesocket(s);
		char err[128];
		e.GetErrorMessage(err, 128);	
		pDlg->InsertNewChatInfo("文件打开失败:"+CString(err));
		delete lp; lp = NULL;
		return 2;
	}
	lp->m_pFile = &file;

	// 打开文件后生成文件信息字符串strFileInfo
	CString strFileInfo;
	CMsgBag mbTool;
	tagPacketParam pp;

	SYSTEMTIME timeNow;
	GetSystemTime(&timeNow);
	CString strTime;
	strTime.Format("%u-%u-%u  %u:%u:%u", timeNow.wYear, timeNow.wMonth, timeNow.wDay, timeNow.wHour, timeNow.wMinute, timeNow.wSecond);
	float fFileLength = (float)file.GetLength()/1024/1024;
	CString strFileLength;
	strFileLength.Format("%0.1fM", fFileLength);

	/////////////////////////////////////////
	//打包发送文件信息
	pp.order      = "2100";
	pp.UserId	  = lp->m_strMyId;
	pp.UserName   = strFileLength;
	pp.UserPsw    = file.GetFileName();	
	pp.UserDptm   = strTime;	
	pp.paramNum   = 4;
	mbTool.DataPackage(strFileInfo, &pp);

	// 开始发送文件信息包
	if(SOCKET_ERROR  == send(s, strFileInfo.GetBuffer(0), strFileInfo.GetLength(), MSG_PARTIAL))
	{
		closesocket(s);
		file.Close();
		pDlg->InsertNewChatInfo("异常原因导致传送文件信息 [" + lp->m_strFileName + "] 失败!");
		delete lp; lp = NULL;
		return 3;		
	}
	
	pDlg->GetDlgItem(IDC_STCT0)->SetWindowText("正在等待对方回应...");
	pDlg->GetDlgItem(IDC_BTN_CANCLE)->ShowWindow(true);
	//////////////////////////////////////////////////
	//等待对方回应
	char buf[10240]="\0";
	ret = recv(s, buf, 3, MSG_PARTIAL);
	if(ret != 1)
	{
		closesocket(s);
		file.Close();
		pDlg->GetDlgItem(IDC_STCT0)->SetWindowText("");
		if(ret == 2 && strcmp(buf, "NO") == 0)
		{
			pDlg->InsertNewChatInfo("对方无正在发送或接收文件传输,请捎后再试...");
		}
		else if(ret == 3 && strcmp(buf, "OUT") == 0)
		{
			pDlg->InsertNewChatInfo("对方响应文件传输请求超时,请捎后再试...");
		}
		else 
		{
			pDlg->InsertNewChatInfo("对方拒绝了您的文件[" + lp->m_strFileName + "]传输请求!");
		}
		pDlg->GetDlgItem(IDC_BTN_CANCLE)->ShowWindow(false);
		delete lp; lp = NULL;
		return 4;
	}

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


	// 每次实际读取的字节数变量及已经读取的总大小
	int nBytesRead = 0, nBytesRecv = 0;
	char strSized[10], strPecent[10];
	do // 循环至文件读取完毕
	{
		nBytesRead = file.Read(buf, sizeof(buf));
		if(SOCKET_ERROR  == send(s, buf, nBytesRead, MSG_PARTIAL))
		{
			closesocket(s);
			file.Close();
			pDlg->InsertNewChatInfo("对方中断了文件 [" + lp->m_strFileName + "] 传输!");
			pDlg->GetDlgItem(IDC_STCT0)->SetWindowText("");
			pDlg->GetDlgItem(IDC_STCT1)->SetWindowText("");
			pDlg->GetDlgItem(IDC_STCT2)->SetWindowText("");
			pDlg->GetDlgItem(IDC_STCT3)->SetWindowText("");
			fprog->ShowWindow(false);
			pDlg->GetDlgItem(IDC_BTN_CANCLE)->ShowWindow(false);
			delete lp; lp = NULL;
			return 5;		
		}

		nBytesRecv += nBytesRead;
		//////////////////////////////////////////////////////////////
		//计算已传输大小及完成百分比
		float mSize = (float)nBytesRecv / 1024 / 1024;
		sprintf(strSized, "%0.1fM", mSize);
		sprintf(strPecent, "%0.1f%", ((float)nBytesRecv / file.GetLength()) * 100);
		pDlg->GetDlgItem(IDC_STCT2)->SetWindowText(strSized);
		pDlg->GetDlgItem(IDC_STCT3)->SetWindowText(strPecent);

		///////////////////////////////////////////////////////////////
		//设置进度条
		int nStep = (int)(((float)nBytesRecv / file.GetLength()) * 1000);
		fprog->SetPos(nStep);

		// 判断完成的条件:
		if(nBytesRead < sizeof(buf))
			break;

	} while(TRUE);
	
	// 提示传输成功
	pDlg->InsertNewChatInfo("文件 [" + lp->m_strFileName + "] 传送成功!");
	
	// 关闭资源并返回
	closesocket(s);
	file.Close();

	pDlg->GetDlgItem(IDC_STCT0)->SetWindowText("");
	pDlg->GetDlgItem(IDC_STCT1)->SetWindowText("");
	pDlg->GetDlgItem(IDC_STCT2)->SetWindowText("");
	pDlg->GetDlgItem(IDC_STCT3)->SetWindowText("");
	fprog->ShowWindow(false);
	pDlg->GetDlgItem(IDC_BTN_CANCLE)->ShowWindow(false);
	delete lp; lp = NULL;
	return 0;
}


/////////////////////////////////////////////////////////////////////////////
//获得传输监听套接字
SOCKET CP2P::GetFlieListenSock()
{
	return m_FileListenSocket;
}

/////////////////////////////////////////////////////////////////////////////
//获得文件传输监听端口
WORD CP2P::GetFileListenPort()
{
	return m_Port;
}

/////////////////////////////////////////////////////////////////////////////
//获得文件监听状态
bool CP2P::GetFileListenStatus()
{
	return m_bFileLinstenStatus;
}


/////////////////////////////////////////////////////////////////////////////
//获取文件传输线程句柄
HANDLE CP2P::GetFTHandle()
{
	return m_hdlFT;
}

/////////////////////////////////////////////////////////////////////////////
//获取文件传输线程参数结构体
_ThreadParam* CP2P::GetFtThreadParam()
{
	return m_ftParam;
}

void CP2P::CloseFileSocket()
{
	closesocket(m_FileListenSocket);
}

⌨️ 快捷键说明

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