📄 chatdlg.cpp
字号:
{
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 + -