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

📄 chatdlg.cpp

📁 利用Visual C++的Windows SOCKET网络编程实现局域网内正在使用本程序的所有主机的群聊、两主机之间的点对点聊天和文件传送功能
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	{
		MessageBox("创建私聊套接字失败!");
		return FALSE;
	}

	SOCKADDR_IN ownSock3;
	ownSock3.sin_family=AF_INET;					//设置地址,端口
	ownSock3.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
	ownSock3.sin_port=htons(55176);

	if(SOCKET_ERROR==bind(m_priSocket,(SOCKADDR*)&ownSock3,sizeof(SOCKADDR)))	//绑定
	{
		MessageBox("私聊绑定失败!");
		return FALSE;
	}
	if(SOCKET_ERROR==WSAAsyncSelect(m_priSocket,m_hWnd,UM_PRISOCK,FD_READ))
		//注册私聊广播网络读取事件
	{
		MessageBox("注册私聊网络读取事件失败!");
		return FALSE;
	}


	//建立文件传输控制信息套接字
	m_fileSocket=WSASocket(AF_INET,SOCK_DGRAM,0,NULL,0,0);		//采用UDP
	if(INVALID_SOCKET==m_fileSocket)
	{
		MessageBox("创建文件传输套接字失败!");
		return FALSE;
	}

	SOCKADDR_IN ownSock4;
	ownSock4.sin_family=AF_INET;					//设置地址,端口
	ownSock4.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
	ownSock4.sin_port=htons(55178);

	if(SOCKET_ERROR==bind(m_fileSocket,(SOCKADDR*)&ownSock4,sizeof(SOCKADDR)))	//绑定
	{
		MessageBox("文件传输绑定失败!");
		return FALSE;
	}
	//listen(m_fileSocket,5);
	if(SOCKET_ERROR==WSAAsyncSelect(m_fileSocket,m_hWnd,UM_FILECONNSOCK,FD_READ))
		//注册文件传输控制信息单播网络读取事件
	{
		MessageBox("注册文件传输网络读取事件失败!");
		return FALSE;
	}


	return TRUE;
}


////////////////////以下为检测在线用户,建立和维护用户列表的函数////////////////////

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

		/*broadSock.sin_family=AF_INET;
		broadSock.sin_addr.s_addr=INADDR_BROADCAST;
		broadSock.sin_port=htons(55170);*/

		WSARecvFrom(m_bSocket,&wsabuf,1,&dwRead,&dwFlag,(SOCKADDR*)&broadSock,&len,NULL,NULL);
			//接收广播消息

		/*CString str;	
		str.Format("%s",inet_ntoa(broadSock.sin_addr));
		MessageBox(str);*/

		/*CString str,strTemp,strTemp1;
		HOSTENT *pHost;
		pHost=gethostbyaddr((char*)&broadSock.sin_addr.S_un.S_addr,4,AF_INET);
		strTemp.Format("%s %s",pHost->h_name,inet_ntoa(broadSock.sin_addr));
		strTemp1.Format("%s",inet_ntoa(broadSock.sin_addr));
		GetDlgItemText(IDC_EDIT_USER,str);
		str+=strTemp+"\r\n";
		SetDlgItemText(IDC_EDIT_USER,str);*/

		CChatUser *pUser=new CChatUser(broadSock);	//将收到的用户信息保存到CChatUser类的实例中
		CString str="in";
		int i,size;
		BOOL haveNotAdd=TRUE;	//“未加入用户列表”布尔变量,初始化为真
		if(str==wsabuf.buf)		//如果收到的广播消息为“in”,即有用户启动程序
		{
			size=m_userArray.GetSize();		//取得已加入用户列表的用户个数
			for(i=0;i<size;i++)
			{
				if(pUser->m_host_IP==((CChatUser*)m_userArray.GetAt(i))->m_host_IP)
				{//如果发送广播的用户的IP与用户列表中某个用户的IP一致
					haveNotAdd=FALSE;	//则将“未加入用户列表”布尔变量设化为假					
					break;
				}
			}

			if(haveNotAdd)	//如果发送广播的用户未加入用户列表
			{
				m_userArray.Add(pUser);	//将对应该用户的CChatUser类的实例加入到用户序列当中

				((CListBox*)GetDlgItem(IDC_LIST_USER))->AddString(pUser->m_host_name+" --> "+pUser->m_host_IP);	
					//在主对话框的用户列表框中,加入该用户的主机名和IP

				//if(m_ownHost->h_addr_list[0]!=pHost->h_addr_list[0])
				//if(m_ownHost->h_addr_list[0]!=inet_ntoa(broadSock.sin_addr))
				//if(inet_ntoa(m_ownADDR.sin_addr)!=inet_ntoa(broadSock.sin_addr))
				//if(strcmp(inet_ntoa(m_ownADDR.sin_addr),inet_ntoa(broadSock.sin_addr)))

				if(m_ownIP!=pUser->m_host_IP)	//如果收到的广播不是自己发送的(既是其他主机发送的)
				{//则向发送广播的主机,单播一个数据包,将本机的主机名和IP等告知该主机
					SOCKADDR_IN singleSock;	//定义地址结构体
					WSABUF wsabuf;	//定义数据发送缓冲
					DWORD dwSend;	//实际发送字节数
					int len;
					CString str="";		//发送数据为空

					singleSock.sin_family=AF_INET;
					singleSock.sin_addr.s_addr=broadSock.sin_addr.s_addr;//目的地址为发送广播的主机地址
					singleSock.sin_port=htons(55172);	//单播端口

					len=str.GetLength();		//设定数据发送缓冲
					wsabuf.buf=str.GetBuffer(len);
					wsabuf.len=len+1;
					WSASendTo(m_sSocket,&wsabuf,1,&dwSend,0,(SOCKADDR*)&singleSock,sizeof(SOCKADDR),NULL,NULL);			
						//发送单播数据包
				}
			}
		}
		else		//如果收到的广播信息为“out”,即有用户关闭程序
		{
			size=m_userArray.GetSize();	//获取用户列表的用户个数
			for(i=0;i<size;i++)
			{
				if(pUser->m_host_IP==((CChatUser*)m_userArray.GetAt(i))->m_host_IP)
				{//找到与发送广播的用户IP相同的用户列表记录
					//((CPriChatDlg*)(((CChatUser*)m_userArray.GetAt(i))->m_pChatDlg))->CloseDlg();
					//free(((CChatUser*)m_userArray.GetAt(i))->m_pChatDlg);//销毁与用户对应的私聊对话框
					//free((CChatUser*)m_userArray.GetAt(i));	//销毁记录用户信息的CChatUser类的实例
					m_userArray.RemoveAt(i);	//删除该记录的指针
					((CListBox*)GetDlgItem(IDC_LIST_USER))->DeleteString(i);	//在列表框中清除
					break;
				}
			}
		}
		//test++;
		break;
	}
}


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

		/*singleSock.sin_family=AF_INET;
		singleSock.sin_addr.s_addr=htonl(INADDR_ANY);
		singleSock.sin_port=htons(55172);*/		

		WSARecvFrom(m_sSocket,&wsabuf,1,&dwRead,&dwFlag,(SOCKADDR*)&singleSock,&len,NULL,NULL);
			//接收单播数据

		/*CString str,strTemp;
		HOSTENT *pHost;
		pHost=gethostbyaddr((char*)&singleSock.sin_addr.S_un.S_addr,4,AF_INET);
		strTemp.Format("%s %s",pHost->h_name,inet_ntoa(singleSock.sin_addr));		

		GetDlgItemText(IDC_EDIT_USER,str);
		str+=strTemp+"\r\n";
		SetDlgItemText(IDC_EDIT_USER,str);*/

		CChatUser *pUser=new CChatUser(singleSock);//将收到的用户信息保存到CChatUser类的实例中

		int i,size;
		BOOL haveNotAdd=TRUE;	//“未加入用户列表”布尔变量,初始化为真
		size=m_userArray.GetSize();		//取得已加入用户列表的用户个数
		for(i=0;i<size;i++)
		{
			if(pUser->m_host_IP==((CChatUser*)m_userArray.GetAt(i))->m_host_IP)
			{//如果发送广播的用户的IP与用户列表中某个用户的IP一致
				haveNotAdd=FALSE;	//则将“未加入用户列表”布尔变量设化为假
				break;
			}
		}

		if(haveNotAdd)	//如果发送单播的用户未加入用户列表
		{
			m_userArray.Add(pUser);	//将对应该用户的CChatUser类的实例加入到用户序列当中
			((CListBox*)GetDlgItem(IDC_LIST_USER))->AddString(pUser->m_host_name+" --> "+pUser->m_host_IP);
				//在主对话框的用户列表框中,加入该用户的主机名和IP
		}
		
		break;
	}
}


//更新用户列表函数
void CChatDlg::UpdateUserList()
{
	SOCKADDR_IN broadSock;	//定义地址结构体
	WSABUF wsabuf;			//定义数据发送缓冲
	DWORD dwSend;			//实际发送字节数
	int len;
	//char *smsg="This is a test!!";
	CString str="in";		//广播数据为“in”

	broadSock.sin_family=AF_INET;
    broadSock.sin_addr.s_addr=INADDR_BROADCAST;	//目的地址为广播地址
	broadSock.sin_port=htons(55170);	//广播端口

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


//“刷新列表”按钮的响应函数
void CChatDlg::OnUpdateUserList() 
{
	// TODO: Add your control notification handler code here
	UpdateUserList();		//调用更新用户列表函数
}


//发送“离开”消息函数
void CChatDlg::Leave()
{
	SOCKADDR_IN broadSock;	//定义地址结构体
	WSABUF wsabuf;			//定义数据发送缓冲
	DWORD dwSend;			//实际发送字节数
	int len;
	//char *smsg="This is a test!!";
	CString str="out";		//广播数据为“out”

	broadSock.sin_family=AF_INET;
    broadSock.sin_addr.s_addr=INADDR_BROADCAST;	//目的地址为广播地址
	broadSock.sin_port=htons(55170);	//广播端口

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

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


//////////////////////////////////以下为群聊的函数////////////////////////////////////////////

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

		WSARecvFrom(m_pubSocket,&wsabuf,1,&dwRead,&dwFlag,(SOCKADDR*)&pubChatSock,&len,NULL,NULL);
			//接收群聊信息

		CString str,strTemp;
		//strTemp=wsabuf.buf;

		//获取发信息的用户的主机名
		HOSTENT * pHost;
		pHost=gethostbyaddr((char*)&pubChatSock.sin_addr.S_un.S_addr,4,AF_INET);


		//在群聊消息接收编辑框中显示发送者的主机名和所发送的信息
		GetDlgItemText(IDC_EDIT_PUB_RECV,str);
		strTemp.Format("%s",pHost->h_name);
		str+=strTemp+":\r\n"+wsabuf.buf+"\r\n\r\n";
		SetDlgItemText(IDC_EDIT_PUB_RECV,str);

		//令编辑框的滚动条自动滚动到最下面
		int nLen=((CEdit*)GetDlgItem(IDC_EDIT_PUB_RECV))->SendMessage(WM_GETTEXTLENGTH);//获取编辑框文本长度
		((CEdit*)GetDlgItem(IDC_EDIT_PUB_RECV))->SetSel(nLen,nLen,FALSE);//选定文本最后位置

		break;
	}
}


//发送群聊信息的函数(主对话框中“发送”按钮的消息响应函数)
void CChatDlg::OnBtnPubSend() 
{
	// TODO: Add your control notification handler code here
	SOCKADDR_IN pubChatSock;	//定义地址结构体
	WSABUF wsabuf;				//定义数据发送缓冲
	DWORD dwSend;				//实际发送字节数
	int len;
	
	CString str,strTemp;
	GetDlgItemText(IDC_EDIT_PUB_SEND,str);	//取得发送编辑框中文本
	if(""==str)					//如果发送编辑框中文本为空
	{
		MessageBox("不能发送空消息!");
		return;
	}

	/*GetDlgItemText(IDC_EDIT_PUB_RECV,strTemp);

⌨️ 快捷键说明

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