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

📄 lancommuniondlg.cpp

📁 局域网实现聊天,并传输文件,功能较齐全,可添加用户!欢迎大家下载!
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// LANCommunionDlg.cpp : implementation file
//
/********************************************************
 *			  局域网文件传输     聊天工具加强版		    *
 *			  合肥工业大学						        *
 *			  计算机科学与技术	计算机04-5班		    *
 *			  Wi-Fi			    2007年7月8日			*
 *			  加强版完成日期    2007年9月25日			*
 *			  文件传输端口		5200     				*
 *			  聊天	端口		5208    				*
 ********************************************************/
#include "stdafx.h"
#include "LANCommunion.h"
#include "LANCommunionDlg.h"

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

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
struct	SAVEFILEPARAM
{
	SOCKET				sock;
	CLANCommunionDlg*	pCLAN;
};
typedef		SAVEFILEPARAM	BROADCAST;	
struct	SENDFILEPARAM
{
	CString				pathName;
	CString				ip;
	char				fileName[NAMELENGTH];
	CLANCommunionDlg*	pCLAN;
};
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
CString	GetError(	DWORD	err	)
{
	CString strError;
	switch(err)
	{
	case WSANOTINITIALISED:
		strError="初始化错误";
		break;
	case WSAENOTCONN:
		strError="对方没有启动";
		break;
	case WSAEWOULDBLOCK :
		strError="对方已经关闭";
		break;
	case WSAECONNREFUSED:
		strError="连接的尝试被拒绝";
		break;
	case WSAENOTSOCK:
		strError="在一个非套接字上尝试了一个操作";
		break;
	case WSAEADDRINUSE:
		strError="特定的地址已在使用中";
		break;
	case WSAECONNRESET:
		strError="与主机的连接被关闭";
		break;
	default:
		strError="一般错误";	
	}
	return strError;
	
}
/////////////////////////////////////////////////////////////////////////////
/////////////		聊天线程		//////////////////////////////////////////////////
UINT	ChatReceive(	LPVOID	param	)
{
	CHAT*	pChat=(CHAT*)param;
	//客户端地址簇。
	SOCKADDR_IN		addrDest;
	int				len=sizeof(SOCKADDR),err;
	char		cchat[1024];
	while(	true	)
	{	
		CString		schatOld;
		memset(cchat,0,1024);
		schatOld.Empty(	);
		//接收数据。

		err=recvfrom(pChat->sock,cchat,1024,0,(SOCKADDR*)&addrDest,&len);
		if(SOCKET_ERROR==err)
		{
//			AfxMessageBox("接收聊天消息出错。"+GetError(GetLastError()));
			continue;
		}
		//更新聊天内容。
		CWnd*	pMain=AfxGetApp(	)->m_pMainWnd;
		pMain->GetDlgItemText(IDC_EDIT_RECEIVE,schatOld);
		schatOld+="\r\n";
		schatOld+=cchat;
		pMain->SetDlgItemText(IDC_EDIT_RECEIVE,schatOld);
		pMain->GetDlgItem(IDC_EDIT_RECEIVE)->
			SendMessage(WM_VSCROLL,SB_BOTTOM);
		Sleep(55);
	}
	return	0;
}
////////////////////////////////////////////////////////////////////////////
////////////////	单线程接收文件线程				////////////////
UINT	SaveFileSingle(			LPVOID	param	)
{
	SAVEFILEPARAM	sp;
	sp.pCLAN=((SAVEFILEPARAM*)param)->pCLAN;
	sp.sock=((SAVEFILEPARAM*)param)->sock;

	CSocket	sock;
	sock.Attach(	sp.sock	);
	
	DWORD	Length;
	char	fileName[NAMELENGTH];
	CString			savePathName;
	int				modal,err;
	memset(fileName,0,NAMELENGTH);
	
	
	err=sock.Receive(&Length,sizeof(DWORD));//接收文件长度
	if(0==err)
	{
		AfxMessageBox("连接被关闭了。");
		sock.Close(		);
		return	0;
	}
	if(SOCKET_ERROR==err)
	{
		AfxMessageBox(GetError(GetLastError(	)));
		sock.Close(		);
		return	0;
	}
	err=sock.Receive(fileName,NAMELENGTH);//接收文件名
	if(0==err)
	{
		AfxMessageBox("连接被关闭了。");
		sock.Close(		);
		return	0;
	}
	if(SOCKET_ERROR==err)
	{
		AfxMessageBox(GetError(GetLastError(	)));
		sock.Close(		);
		return	0;
	}

	CFileArrive		dlg;
	dlg.m_fileName.Format("文件\r\n\t%s\r\n\t到达是否接收?",fileName);
	if(	IDCANCEL==dlg.DoModal(	)	)
	{
		sock.Close(		);
		return	0;
	}

	CFileDialog		fdlg(false,NULL,fileName);//保存文件对话框。	
	modal=fdlg.DoModal(	);
	if(IDCANCEL==modal)	
	{
		sock.Close(		);
		return	0; //用户取消保存。
	}
	savePathName=fdlg.GetPathName(	);
	//////////////////////////////////////////////////////////////
	int		finish=0;
	DWORD	step=0;
	CFile	file;
	char	buffer[BUFFERSIZE];

	if(	0==file.Open(savePathName,CFile::modeWrite	|CFile::modeCreate|	CFile::typeBinary)	)
	{
		AfxMessageBox("打开要写入的文件出错。");
		sock.Close(		);
		return	0;
	}
	
	CTransportInfoDlg*	pDialog=new	CTransportInfoDlg();	
	sp.pCLAN->SendMessage(UM_CREATE_TRANSPORTDLG,(WPARAM)pDialog);
	pDialog->m_progress.SetRange32(0,Length);
	pDialog->m_progress.SetPos(0);
	DWORD	timeStart,timeEnd,time,speed;
	CString	s;
	timeStart=::GetTickCount(	);

	s.Format(_T("正在接收文件:  %s"),fileName);
	pDialog->m_title.SetWindowText(s);
	
	while(	true	)
	{
		finish=sock.Receive(buffer,BUFFERSIZE);
		if(0==finish)
		break;
		if(SOCKET_ERROR==finish)
		{
			AfxMessageBox(GetError(GetLastError(	)));
			sock.Close(		);
			sp.pCLAN->SendMessage(UM_DELETE_DLG,(WPARAM)pDialog);
			sp.pCLAN->SetFocus(	);
			return	0;
		}

		if(pDialog->m_bEnd)
		{
			sock.Close(		);
			sp.pCLAN->SendMessage(UM_DELETE_DLG,(WPARAM)pDialog);
			sp.pCLAN->SetFocus(	);
			return	0;
		}
		file.Write(buffer,finish);
		step+=finish;
		///////////////////////////////////////////////////////
		//更新对传输信息对话框消息。
		pDialog->m_progress.SetPos(step);
		timeEnd=::GetTickCount(	);
		time=timeEnd-timeStart;
		time/=1000;
		if(time>0)
		{
			speed=((step/time)>>10);
			if(1024>speed)	//Speed  is    k/BPS
			{
				s.Format("接收速度为:%dK/BPS",speed);
				pDialog->m_speed.SetWindowText(s);
			}
			else			//Speed	 is		M/BPS
			{
				s.Format("接收速度为:%dM/BPS",speed>>10);
				pDialog->m_speed.SetWindowText(s);
			}
		}
		///////////////////////////////////////////////////////
	}
	file.Close(		);
	sock.Close(		);
	
	sp.pCLAN->SendMessage(UM_DELETE_DLG,(WPARAM)pDialog);
	
	CString		strFinish;
	strFinish.Format("已成功接收文件\r\n\r\n%s",fileName);
	AfxMessageBox(strFinish);

	sp.pCLAN->SetFocus(	);

	return	0;
}
/////////////////////////////////////////////////////////////////////
////////////////	单线程监听有无文件传输连接。	/////////////////
UINT	ListenFileTransport(	LPVOID	param)
{
	CLANCommunionDlg*	pCLAN=(CLANCommunionDlg*)param;
	CSocket				sockServer;

	if (!AfxSocketInit())
	{
		AfxMessageBox("ListenFileTransport		AfxSocketInit(	)失败。");
		return 0;
	}

	if(	0==sockServer.Create(	FILEPORT	)	)
	{
		AfxMessageBox("监听套接字创建失败。");
		return	0;
	}
	if(	0==sockServer.Listen(	)	)
	{
		AfxMessageBox("监听套接字监听失败。");
		sockServer.Close(	);
		return	0;
	}

	//监听套接字创建成功。
	//发送文件按钮可用。
	
	pCLAN->m_SendFile.EnableWindow(true);

	//监听套接字等待连接请求。
	while(	true	)
	{
		CSocket		sockClient;
		if(	0==sockServer.Accept(	sockClient	)	)
		{
			AfxMessageBox("监听套接字接受服务失败。");
			sockServer.Close(	);
			break	;
		}

		//用线程函数来接收文件。

		/////////////////////////////////////////////////////////////////////////////
		SAVEFILEPARAM	param;
		param.sock=sockClient.Detach(	);
		param.pCLAN=pCLAN;

		AfxBeginThread(SaveFileSingle,(LPVOID)&param);
		//////////////////////////////////////////////////////////////////////////////
	}
	sockServer.Close(	);	
	return	0;
}
////////////////		单线程发送文件线程。		///////////////////////////////////
UINT	SendFileSingle(	LPVOID	param	)
{
	if (!AfxSocketInit())
	{
		AfxMessageBox("SendFileSingle		AfxSocketInit(	)失败。");
		return 0;
	}
	
	CLANCommunionDlg*	pCLAN=((SENDFILEPARAM*)param)->pCLAN;	
	CString		ip;
	char		fileName[NAMELENGTH];
	char		buffer[BUFFERSIZE];
	DWORD		Length;
	CFile		file;
	memset(fileName,0,NAMELENGTH);
	strcpy(fileName,((SENDFILEPARAM*)param)->fileName);
	
	ip=((SENDFILEPARAM*)param)->ip;
	
	if(	0==file.Open(((SENDFILEPARAM*)param)->pathName,CFile::modeRead	|	CFile::typeBinary)	)
	{
		return	0;
	}
	Length=file.GetLength(	);
	
	//创建发送套接字准备发送。

	CSocket		sockSend;
	if(0==sockSend.Create(	)	)
	{
		AfxMessageBox("创建发送套接字出错。");
		return	0;
	}

	if(0==sockSend.Connect(	ip,	FILEPORT	)	)
	{
		AfxMessageBox("发送文件连接出错,可能是对方不在线。\r\n"+GetError(GetLastError(	)));
		sockSend.Close(	);
		return	0;
	}
	if(SOCKET_ERROR ==sockSend.Send(&Length,sizeof(DWORD)))//发送文件长度
	{
		AfxMessageBox("发送文件长度出错。\r\n"+GetError(GetLastError(	)));
		sockSend.Close(	);
		return	0;
	}
	if(SOCKET_ERROR ==sockSend.Send(fileName,NAMELENGTH))//发送文件名
	{
		AfxMessageBox("发送文件名出错。\r\n"+GetError(GetLastError(	)));
		sockSend.Close(	);
		return	0;
	}
	DWORD	step=0;
	int		over,err;

	CTransportInfoDlg*	pDialog=new	CTransportInfoDlg();	
	pCLAN->SendMessage(UM_CREATE_TRANSPORTDLG,(WPARAM)pDialog);
	pDialog->m_progress.SetRange32(0,Length);
	pDialog->m_progress.SetPos(0);
	DWORD	timeStart,timeEnd,time,speed;
	CString	s;
	timeStart=::GetTickCount(	);

	s.Format(_T("正在发送文件:  %s"),fileName);
	pDialog->m_title.SetWindowText(s);
	//发送文件内容。
	do
	{
		file.Seek(step,CFile::begin);
		over=file.Read(buffer,BUFFERSIZE);
		err=sockSend.Send(buffer,over);
		if(	BUFFERSIZE>over	)
			break;	
		if(SOCKET_ERROR==err)
		{
			AfxMessageBox("发送文件内容出错。\r\n"+GetError(GetLastError(	)));			
			sockSend.Close(		);
			pCLAN->SendMessage(UM_DELETE_DLG,(WPARAM)pDialog);
			pCLAN->SetFocus(	);
			return	0;
		}
		
		if(pDialog->m_bEnd)
		{
			sockSend.Close(		);
			pCLAN->SendMessage(UM_DELETE_DLG,(WPARAM)pDialog);
			pCLAN->SetFocus(	);
			return	0;
		}

		step+=err;

		///////////////////////////////////////////////////////
		//更新对传输信息对话框消息。
		pDialog->m_progress.SetPos(step);
		timeEnd=::GetTickCount(	);
		time=timeEnd-timeStart;
		time/=1000;
		if(time>0)
		{
			speed=((step/time)>>10);
			if(1024>speed)	//Speed  is    k/BPS
			{
				s.Format("发送速度为:%dK/BPS",speed);
				pDialog->m_speed.SetWindowText(s);
			}
			else			//Speed	 is		M/BPS
			{
				s.Format("发送速度为:%dM/BPS",speed>>10);
				pDialog->m_speed.SetWindowText(s);
			}
		}
		///////////////////////////////////////////////////////
		
	}while(	true	);
	file.Close(	);
	sockSend.Close(		);
	
	pCLAN->SendMessage(UM_DELETE_DLG,(WPARAM)pDialog);

	CString		strFinish;
	strFinish.Format("已成功发送文件\r\n\r\n%s。",fileName);
	AfxMessageBox(strFinish);

	pCLAN->SetFocus(	);

	delete	(SENDFILEPARAM*)param;
	return	0;
}				
/////////////////////////////////////////////////////////////////////////////
//////////////////////		接收广播消息线程		////////////////////////
UINT	ReceiveBroadcast(	LPVOID	param	)
{
	SOCKET	sock=((BROADCAST*)param)->sock;
	CLANCommunionDlg*	pCLAN=((BROADCAST*)param)->pCLAN;
	int		err,nListItemCount,nListItemDelete;
	bool	del,bItemExist;
	char	buf[210];
	char	bufHost[200];
	CString	ip,strFind;
	sockaddr_in		addrFrom;
	int		len=sizeof(sockaddr);
	
//	CListCtrl*	pList=(CListCtrl*)pCLAN->GetDlgItem(IDC_LIST_USER);
	
	while(	true	)
	{
		del=false;
		memset(bufHost,0,200);
		memset(buf,0,210);
		ip.Empty(	);
		err=recvfrom(sock,buf,210,0,(sockaddr*)&addrFrom,&len);
		if(SOCKET_ERROR==err)
		{
//			AfxMessageBox("接收广播数据出错。");
			continue;
		}
		ip=inet_ntoa(addrFrom.sin_addr);
		//检查是否为请求返回是否在线的确认消息。
		if(buf[0]=='\t'&&buf[1]=='\t'&&buf[2]=='\t'&&buf[3]=='\t')
		{
			int		iIndex=4;
			int		n=0;
			int		result;
			while(0!=buf[iIndex])
				bufHost[n++]=buf[iIndex++];
			//获取主机名
			char	pMyhost[200];
			memset(pMyhost,0,200);
			if(	0==gethostname(pMyhost,200)	);
			else	strcpy(pMyhost,"Anony");
			
			sockaddr_in		addrTo;
			addrTo.sin_addr.S_un.S_addr=addrFrom.sin_addr.S_un.S_addr;
			addrTo.sin_family=AF_INET;
			addrTo.sin_port=htons(RECVPORT);
			
			result=sendto(sock,pMyhost,strlen(pMyhost)+1,0,(sockaddr*)&addrTo,sizeof(sockaddr));
			if(SOCKET_ERROR==result)
			{
				AfxMessageBox("发送返回在线确认消息出错。");
				continue;
			}
			result=sendto(sock,pMyhost,strlen(pMyhost)+1,0,(sockaddr*)&addrTo,sizeof(sockaddr));

⌨️ 快捷键说明

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