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

📄 chatdlg.cpp

📁 利用Visual C++的Windows SOCKET网络编程实现局域网内正在使用本程序的所有主机的群聊、两主机之间的点对点聊天和文件传送功能
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	strTemp+=m_ownHost+":\r\n"+str+"\r\n\r\n";
	SetDlgItemText(IDC_EDIT_PUB_RECV,strTemp);*/

	pubChatSock.sin_family=AF_INET;
    pubChatSock.sin_addr.s_addr=INADDR_BROADCAST;	//目的地址为广播地址
	pubChatSock.sin_port=htons(55174);	//群聊端口

	//设定数据发送缓冲
	len=str.GetLength();
	wsabuf.buf=str.GetBuffer(len);
	wsabuf.len=len+1;
	
	//sendto(m_bSocket,smsg,256,0,(sockaddr*)&broadSock,sizeof(SOCKADDR));
	WSASendTo(m_pubSocket,&wsabuf,1,&dwSend,0,(SOCKADDR*)&pubChatSock,sizeof(SOCKADDR),NULL,NULL);
		//发送群聊信息

	SetDlgItemText(IDC_EDIT_PUB_SEND,"");	//清空发送编辑框中文本
}

///////////////////////////////////////////////////////////////////////////////////////////////


///////////////////以下为私聊的函数(有一部分私聊函数在CPriChatDlg类中定义)/////////////////////

//用户双击主对话框用户列表中某用户的响应函数
void CChatDlg::OnDblclkListUser() 
{
	// TODO: Add your control notification handler code here
	int i=((CListBox*)GetDlgItem(IDC_LIST_USER))->GetCurSel();//获取用户双击列表框中第几个在线用户
	/*CString str;
	str.Format("%d",i);
	MessageBox(str);*/
	CChatUser * ptrUser=((CChatUser*)m_userArray.GetAt(i));//将被选中的用户信息从用户序列中取出
	if(NULL==ptrUser->m_pChatDlg)	//如果与被选中用户私聊的对话框还未创建
	{
		//创建私聊对话框
		ptrUser->m_pChatDlg=new CPriChatDlg(ptrUser->m_host_IP,ptrUser->m_host_name,this);	
		ptrUser->m_pChatDlg->Create(IDD_PRICHAR_DIALOG);

		if(m_ownIP==ptrUser->m_host_IP)		//如果用户双击的是自己
			ptrUser->m_pChatDlg->SetWindowText("与自己聊天");	//设定对话框标题
		else		//如果用户双击的是其他用户
			ptrUser->m_pChatDlg->SetWindowText("与"+ptrUser->m_host_name+"聊天");//设定对话框标题
	}

	ptrUser->m_pChatDlg->ShowWindow(SW_SHOW);	//显示窗口
	ptrUser->m_pChatDlg->UpdateWindow();		//更新窗口
}


//收到私聊信息的消息响应函数
void CChatDlg::OnPRISock(WPARAM wParam,LPARAM lParam)
{	
	switch(LOWORD(lParam))
	{
	case FD_READ:	//如果为网络读取事件
		//MessageBox("OnPRISock");
		SOCKADDR_IN priChatSock;	//定义地址结构体
		WSABUF wsabuf;				//定义数据发送缓冲
		wsabuf.buf=new char[200];
		wsabuf.len=200;
		DWORD dwRead;				//实际接收字节数
		DWORD dwFlag=0;
		int len=sizeof(SOCKADDR);

		WSARecvFrom(m_priSocket,&wsabuf,1,&dwRead,&dwFlag,(SOCKADDR*)&priChatSock,&len,NULL,NULL);
			//接收私聊信息

		int i,size=m_userArray.GetSize();
		for(i=0;i<size;i++)
		{//查找与发送信息的用户IP相同的,用户列表中的用户数据
			if(priChatSock.sin_addr.S_un.S_addr==((CChatUser*)m_userArray.GetAt(i))->m_addr.sin_addr.S_un.S_addr)
				break;		
		}
		//MessageBox("recv");
		CChatUser * ptrUser=((CChatUser*)m_userArray.GetAt(i));
			//定义指向保存该用户信息的CChatUser类实例的指针

		if(NULL==ptrUser->m_pChatDlg)	//如果与该用户私聊的对话框未创建
		{
			//创建对话框
			ptrUser->m_pChatDlg=new CPriChatDlg(ptrUser->m_host_IP,ptrUser->m_host_name,this);	
			ptrUser->m_pChatDlg->Create(IDD_PRICHAR_DIALOG);
			ptrUser->m_pChatDlg->SetWindowText("与"+ptrUser->m_host_name+"聊天");
		}

		ptrUser->m_pChatDlg->ShowWindow(SW_SHOW);	//显示窗口
		ptrUser->m_pChatDlg->UpdateWindow();		//更新窗口
		
		//GetDlgItem(IDC_EDIT_SENT,(HWND*)ptrUser->m_pChatDlg)->SetWindowText(wsabuf.buf,sizeof(wsabuf.buf)+1);
		CString str;
		//调用CPriChatDlg成员函数SetRecvText,将发送信息者的主机名和其发送的信息
		//显示在私聊对话框的接收信息编辑框中
		str=ptrUser->m_host_name+":\r\n";
		ptrUser->m_pChatDlg->SetRecvText(&str);
		
		str.Format("%s\r\n\r\n",wsabuf.buf);
		ptrUser->m_pChatDlg->SetRecvText(&str);		
		break;
	}
}

///////////////////////////////////////////////////////////////////////////////////////////////


/////////////////以下为文件传输函数(有一部分文件传输函数定义在CPriChatDlg类中)/////////////////

//收到文件传输控制信息的消息响应函数
void CChatDlg::OnFileConnSock(WPARAM wParam,LPARAM lParam)
{
	switch(LOWORD(lParam))
	{
	case FD_READ:	//如果为网络读取事件
		//MessageBox("OnFileConnSock");
		SOCKADDR_IN fileCtrlRecvSock;	//定义地址结构体
		WSABUF wsabuf;					//定义数据发送缓冲
		wsabuf.buf=new char[50];
		wsabuf.len=50;
		DWORD dwRead;					//实际接收字节数
		DWORD dwFlag=0;
		int len=sizeof(SOCKADDR);

		WSARecvFrom(m_fileSocket,&wsabuf,1,&dwRead,&dwFlag,(SOCKADDR*)&fileCtrlRecvSock,&len,NULL,NULL);
			//接收文件传输控制信息

		int i,size=m_userArray.GetSize();
		for(i=0;i<size;i++)
		{//查找与发送信息的用户IP相同的,用户列表中的用户数据
			if(fileCtrlRecvSock.sin_addr.S_un.S_addr==((CChatUser*)m_userArray.GetAt(i))->m_addr.sin_addr.S_un.S_addr)
				break;
		}

		CChatUser * ptrUser=((CChatUser*)m_userArray.GetAt(i));
			//定义指向保存该用户信息的CChatUser类实例的指针

		if(NULL==ptrUser->m_pChatDlg)	//如果与该用户私聊的对话框未创建
		{
			//创建对话框
			ptrUser->m_pChatDlg=new CPriChatDlg(ptrUser->m_host_IP,ptrUser->m_host_name,this);	
			ptrUser->m_pChatDlg->Create(IDD_PRICHAR_DIALOG);
			ptrUser->m_pChatDlg->SetWindowText("与"+ptrUser->m_host_name+"聊天");
		}

		ptrUser->m_pChatDlg->ShowWindow(SW_SHOW);	//显示窗口
		ptrUser->m_pChatDlg->UpdateWindow();		//更新窗口
		

		CString str=wsabuf.buf;		//保存接收数据

		if("go"==str)	//如果收到数据“go”,即接收方同意接收文件
		{
			AfxBeginThread(FileSendProc,ptrUser);	//启动文件发送线程


			/*注释部分为单线程模式
			ptrUser->m_pChatDlg->FileButtonCtrl(0x00);

			CString strTemp;			
			strTemp="文件传送中,请稍候。\r\n\r\n";
			ptrUser->m_pChatDlg->SetRecvText(&strTemp);

			CSocket sockSrvr;
			sockSrvr.Create(800);

			sockSrvr.Listen();
			CSocket sockRecv;
			sockSrvr.Accept(sockRecv);

			SOCKET_STREAM_FILE_INFO	StreamFileInfo;
			WIN32_FIND_DATA FindFileData;

			FindClose(FindFirstFile(ptrUser->m_pChatDlg->m_pathName,&FindFileData));
			memset(&StreamFileInfo,0,sizeof(SOCKET_STREAM_FILE_INFO));
			strcpy(StreamFileInfo.szFileTitle,ptrUser->m_pChatDlg->m_myFile.GetFileTitle());

			StreamFileInfo.dwFileAttributes     =       FindFileData.dwFileAttributes;
			StreamFileInfo.ftCreationTime       =       FindFileData.ftCreationTime;
			StreamFileInfo.ftLastAccessTime     =       FindFileData.ftLastAccessTime;
			StreamFileInfo.ftLastWriteTime      =       FindFileData.ftLastWriteTime;
			StreamFileInfo.nFileSizeHigh        =       FindFileData.nFileSizeHigh;
			StreamFileInfo.nFileSizeLow         =       FindFileData.nFileSizeLow;

			sockRecv.Send(&StreamFileInfo,sizeof(SOCKET_STREAM_FILE_INFO));

			UINT dwRead=0;
			while(dwRead<StreamFileInfo.nFileSizeLow)
			{
				byte* data = new byte[1024];
				UINT dw=ptrUser->m_pChatDlg->m_myFile.Read(data, 1024);
				sockRecv.Send(data, dw);
				dwRead+=dw;
			}
			ptrUser->m_pChatDlg->m_myFile.Close();

			sockRecv.Close();
						
			strTemp="文件发送完毕!\r\n\r\n";
			ptrUser->m_pChatDlg->SetRecvText(&strTemp);	
			AfxMessageBox("发送完毕!");

			ptrUser->m_pChatDlg->FileButtonCtrl(0x90);*/			
		}

		else if("stop"==str)	//如果收到数据“stop”,即接收方拒绝接收文件
		{
			str=ptrUser->m_host_name+"拒绝接收该文件!\r\n\r\n";
			ptrUser->m_pChatDlg->SetRecvText(&str);		//显示对方拒绝接收文件
			ptrUser->m_pChatDlg->FileButtonCtrl(0x90);	
				//Enable“传输文件”和“退出”按钮,Disable“接收文件”和“拒绝接收”按钮
		}

		else	//如果收到其他信息,即为其他用户向你发送的文件的文件名
		{		
			
			//MessageBox("recv");
			
			//GetDlgItem(IDC_EDIT_SENT,(HWND*)ptrUser->m_pChatDlg)->SetWindowText(wsabuf.buf,sizeof(wsabuf.buf)+1);
			//CString str;
			//str=ptrUser->m_host_name+":\r\n";
			//ptrUser->m_pChatDlg->SetRecvText(&str);
			str=ptrUser->m_host_name+"向你发送此文件:"+wsabuf.buf+"\r\n请按'接收文件'按钮或'拒绝接收'按钮\r\n\r\n";
				//显示某用户向你发送文件
			//str="haha\r\n";
			//str.Format("%s\r\n\r\n",wsabuf.buf);
			ptrUser->m_pChatDlg->m_fileTitle=wsabuf.buf;//保存文件名
			ptrUser->m_pChatDlg->SetRecvText(&str);		//显示文件名
			ptrUser->m_pChatDlg->FileButtonCtrl(0x60);
				//Disable“传输文件”和“退出”按钮,Enable“接收文件”和“拒绝接收”按钮
		}
	break;
	}
}


//文件发送线程函数
UINT FileSendProc(LPVOID lParam)
{
	//MessageBox("WorkThreadProc");
	CChatUser *ptrUser = (CChatUser *)lParam;
		//取出收到的信息(指向保存接收方信息的CChatUser实例的指针)

	ptrUser->m_pChatDlg->FileButtonCtrl(0x00);
		//Disable“传输文件”、“接收文件”、“拒绝接收”和“退出”按钮

	CString strTemp;			
	strTemp="文件发送中,请稍候。\r\n\r\n";
	ptrUser->m_pChatDlg->SetRecvText(&strTemp);

	
	CSocket sockSrvr;		//建立异步套接字
	sockSrvr.Create(55180);	//端口为55180

	sockSrvr.Listen();		//开始监听

	CSocket sockRecv;		//建立异步套接字
	sockSrvr.Accept(sockRecv);	//接收请求

	SOCKET_STREAM_FILE_INFO	StreamFileInfo;		//定义描述文件信息结构体
	WIN32_FIND_DATA FindFileData;

	//复制文件信息
	FindClose(FindFirstFile(ptrUser->m_pChatDlg->m_pathName,&FindFileData));
	memset(&StreamFileInfo,0,sizeof(SOCKET_STREAM_FILE_INFO));
	strcpy(StreamFileInfo.szFileTitle,ptrUser->m_pChatDlg->m_myFile.GetFileTitle());

	StreamFileInfo.dwFileAttributes     =       FindFileData.dwFileAttributes;
	StreamFileInfo.ftCreationTime       =       FindFileData.ftCreationTime;
	StreamFileInfo.ftLastAccessTime     =       FindFileData.ftLastAccessTime;
	StreamFileInfo.ftLastWriteTime      =       FindFileData.ftLastWriteTime;
	StreamFileInfo.nFileSizeHigh        =       FindFileData.nFileSizeHigh;
	StreamFileInfo.nFileSizeLow         =       FindFileData.nFileSizeLow;

	sockRecv.Send(&StreamFileInfo,sizeof(SOCKET_STREAM_FILE_INFO));//发送文件信息

	DWORD dwReadlo=0;	//已发送大小的低双字
	DWORD dwReadhi=0;	//已发送大小的高双字
	short present=0;	//已发送百分比
	unsigned __int64 temp1=(StreamFileInfo.nFileSizeHigh*2^32+StreamFileInfo.nFileSizeLow)/100;
		//文件大小的1/100
	unsigned __int64 temp2;

	//发送文件
	while(dwReadhi<=StreamFileInfo.nFileSizeHigh)
	{
		while(dwReadlo<StreamFileInfo.nFileSizeLow)
		{
			byte* data = new byte[1024];
			UINT dw=ptrUser->m_pChatDlg->m_myFile.Read(data, 1024);	//读取1KB
			sockRecv.Send(data, dw);	//发送
			free(data);			//释放内存
			dwReadlo+=dw;

			//更新文件发送进度
			if(0==StreamFileInfo.nFileSizeHigh)	//如果文件小于4GB
			{
				if(dwReadlo>=present*temp1)		//如果多传了1%
				{
					strTemp.Format("%d",present);
					ptrUser->m_pChatDlg->SetProgress(&strTemp,TRUE);//更新进度
					present++;
				}
			}
			else	//如果文件大于4GB
			{
				temp2=dwReadhi*2^32+dwReadlo;	//已发送文件大小
				if(temp2>=present*temp1)		//如果多传了1%
				{
					strTemp.Format("%d",present);
					ptrUser->m_pChatDlg->SetProgress(&strTemp,TRUE);//更新进度
					present++;
				}
			}
		}
		dwReadlo=0;
		dwReadhi++;
	}

	strTemp.Format("%d",100);	//发送完毕,将进度置为100%
	ptrUser->m_pChatDlg->SetProgress(&strTemp,TRUE);//更新进度

	ptrUser->m_pChatDlg->m_myFile.Close();	//关闭文件

	sockRecv.Close();	//关闭套接字
	
	//显示提示信息
	strTemp="文件发送完毕!\r\n\r\n";
	ptrUser->m_pChatDlg->SetRecvText(&strTemp);	
	//AfxMessageBox("发送完毕!");

	ptrUser->m_pChatDlg->FileButtonCtrl(0x90);
		//Enable“传输文件”和“退出”按钮,Disable“接收文件”和“拒绝接收”按钮
	ptrUser->m_pChatDlg->SetProgress(&strTemp,FALSE);	//清除文件进度显示
	return 0;
}

⌨️ 快捷键说明

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