自制即时通信系统:socket网络编程(6)

来源:互联网 发布:js控制div隐藏 编辑:程序博客网 时间:2024/05/23 15:06

本节介绍剩下的用例:个人信息修改用例、用户查询用例、客户信息传输用例、退出系统用例;
客户端中的个人信息修改用例步骤以及主要代码:
1)输入更改内容
2)本地格式校验
3)发送更改资料请求
4)返回反馈信息
5)更新用户资料命令

void CSetDlg::OnOK(){// TODO: Add extra validation hereUpdateData(TRUE);//发送修改个人信息到服务器cln_set set;set.magic=0x54;set.flags=0x04;sprintf(set.id,"%s",m_strId);sprintf(set.name,"%s",m_strName);sprintf(set.city,"%s",m_strCity);sprintf(set.info,"%s",m_strInfo);set.age=m_ByteAge;if(m_strSex=="男")set.sex=0x01;elseif(m_strSex=="女")set.sex=0x02;elseif(m_strSex=="其它")set.sex=0x04;extern CTCPSocket sock;char buf[888];memset(buf,'\0',sizeof(buf));int num;if((num=sock.rio_writeline(sock.sock, &set, sizeof(set), 0))<=0)::MessageBox(NULL,"发送请求失败","system error",MB_OK|MB_ICONERROR);//接受响应int size=sock.rio_readlineb(sock.rio, buf, sizeof(buf));if(size>0){header *serv =(header *)buf;if((serv->magic==0x55) && (serv->flags==0x04)){::MessageBox(NULL,"修改成功","system error",MB_OK|MB_ICONERROR);//修改成功则更改本地好友列表FriendMsg p;p.name=m_strName;p.sex=m_strSex;p.age=m_ByteAge;p.city=m_strCity;p.info=m_strInfo;CWnd *pWnd=GetParent();((CIMPropertySheet *)pWnd)->page1->listmsg(&p);//刷新好友列表的自己//待写//更新LastMsgLastMsg.name=m_strName;LastMsg.sex=m_strSex;LastMsg.age=m_ByteAge;LastMsg.city=m_strCity;LastMsg.info=m_strInfo;}elseif((serv->magic==0x54) && (serv->flags==0x04))::MessageBox(NULL,"修改失败","system error",MB_OK|MB_ICONERROR);else::MessageBox(NULL,"数据包不在服务范围内","system error",MB_OK|MB_ICONERROR);}//CPropertyPage::OnOK();}void CSetDlg::reset(){m_strName=LastMsg.name;m_strSex=LastMsg.sex;m_ByteAge=LastMsg.age;m_strCity=LastMsg.city;m_strInfo=LastMsg.info;UpdateData(FALSE);}void CSetDlg::OnReset(){// 重置reset();}

--------------------------------------------------------------------------------------------------------------

客户端中的用户查询用例步骤以及主要代码:
1)按ID/昵称查找,在线查找,查找全部
2)发送查询好友请求
3)客户端返回查询结果
4)客户端显示查询结果

void CAddDlg::OnButtonQueryall() {// TODO: 查询所有好友信息cln_query query;memset(&query,'\0',sizeof(query));query.magic=0x54;query.flags=0x08;extern CTCPSocket sock;memset(servbuf,'\0',sizeof(servbuf));int num;if((num=sock.rio_writeline(sock.sock, &query, sizeof(query), 0))<=0)::MessageBox(NULL,"发送请求失败","system error",MB_OK|MB_ICONERROR);//接受响应int size=sock.rio_readlineb(sock.rio, servbuf, sizeof(servbuf));if(size>0){serv_query *serv_answer=(serv_query *)servbuf;if((serv_answer->magic==0x55) && (serv_answer->flags==0x08))//查询成功,插入查询列表{DelAllData();//删除之前查询结果if(serv_answer->friend_num==0)::MessageBox(NULL,"查询结果为空","system error",MB_OK|MB_ICONERROR);else{for(int i=0; i<serv_answer->friend_num;){AddItem(serv_answer, i); i++;}}}elseif((serv_answer->magic==0x54) && (serv_answer->flags==0x08))::MessageBox(NULL,"查询失败","system error",MB_OK|MB_ICONERROR);else::MessageBox(NULL,"数据包不在服务范围内","system error",MB_OK|MB_ICONERROR);}}

--------------------------------------------------------------------------------------------------------------

客户端中的即时信息传输用例步骤以及主要代码:
1)选择发送内容
2)获取发送方地址,端口,不在线则做离线处理
3)传输信息
5)对方显示信息或在服务器中插入离线信息

unsigned int WINAPI CIMDlg::RecvFromThreadFunc(void *vargp)//循环接收UDP消息线程{CIMDlg * obj=(CIMDlg *)vargp;for(;;){struct sockaddr_in clntAddr;int clntAddrLen= sizeof(clntAddr);if(UDPRecvFlags==0){int numBytsRcvd = recvfrom(UDPServ, UDPRecvBuf, 113, 0 , (struct sockaddr *)&clntAddr, &clntAddrLen);if(numBytsRcvd < 0)continue;else{UDPRecvFlags=1;obj->UDPServThreadFunc();}}}return 1;}void CIMDlg::UDPServThreadFunc(){if(UDPRecvFlags==1 || UDPOfflineMsgFlags==1)SendMessage(newfriendmsg);//发现有好友消息传来,向主线程发送消息进行通知}unsigned int WINAPI CIMDlg::UDPClientThreadFunc(CChat * chat)//发送好友消息函数{if(strcmp(chat->SelfMsg.state,"在线")==0){int size=strlen(chat->m_strChat);if(size==0)return 0;//暂时不足点,发送数据空间可压缩UDP_Package *pack=new UDP_Package;sprintf(pack->id,"%s",chat->SelfMsg.selfid);sprintf(pack->message,"%s",chat->m_strChat);UDPClient = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);//必须在此处建立套接字,在init()中不行if(UDPClient<0)printf("socket() failed\n");//聊天窗口点击发送时调用此函数,将聊天信息发送给好友struct sockaddr_in servAddr;int servAddrLen=sizeof(servAddr);memset(&servAddr, 0, sizeof(servAddr));servAddr.sin_family = AF_INET;servAddr.sin_addr.s_addr=htonl(chat->SelfMsg.ip);servAddr.sin_port=htons(chat->SelfMsg.port);//sprintf(buf,"%s",pack);int numBytsRcvd = sendto(UDPClient, (char *)pack, 112, 0 , (struct sockaddr *)&servAddr, servAddrLen);if(numBytsRcvd < 0){::MessageBox(NULL,"发送消息失败","system error",MB_OK|MB_ICONERROR);return 0;}else//发送成功则将消息显示在聊天窗口中{//EnterCriticalSection(&g_cs);// 进入临界区chat->GetDlgItemText(IDC_EDITOLDMSG,chat->strShow);chat->strShow+=chat->SelfMsg.selfname;chat->strShow+=":";chat->strShow+="\r\n";chat->strShow+=chat->m_strChat;chat->strShow+="\r\n";chat->SetDlgItemText(IDC_EDITOLDMSG, chat->strShow);chat->m_strChat="";//LeaveCriticalSection(&g_cs); // 离开临界区}closesocket(UDPClient);delete pack;}//好友在线信息处理完毕else{//此处添加好友不在线时信息发送处理extern CTCPSocket sock;cln_offline_msg offline;memset(&offline,'\0',sizeof(offline));offline.magic=0x54;offline.flags=-128;sprintf(offline.resid,"%s",chat->SelfMsg.selfid);sprintf(offline.desid,"%s",chat->SelfMsg.userid);sprintf(offline.message,"%s",chat->m_strChat);int num;if((num=sock.rio_writeline(sock.sock, &offline, sizeof(offline), 0))<=0)::MessageBox(NULL,"rio_writen() failed","system error",MB_OK|MB_ICONERROR);//将消息显示到记录框chat->GetDlgItemText(IDC_EDITOLDMSG,chat->strShow);chat->strShow+=chat->SelfMsg.selfname;chat->strShow+=":";chat->strShow+="\r\n";chat->strShow+=chat->m_strChat;chat->strShow+="\r\n";chat->SetDlgItemText(IDC_EDITOLDMSG, chat->strShow);chat->m_strChat="";}return 1;}

--------------------------------------------------------------------------------------------------------------

客户端中的退出系统用例步骤以及主要代码:
1)发送退出消息
2)接收服务器反馈消息并正常下线

BOOL CIMPropertySheet::DestroyWindow() {// TODO: 下线通知//关闭TCP套接字cln_offline offline;offline.magic=0x54;offline.flags=0x20;FriendMsg * p=(FriendMsg*)this->page1->m_TreeCtl.GetItemData(this->page1->SelfItem);sprintf(offline.userid,"%s",p->userid);extern CTCPSocket sock;char buf[88];memset(buf,'\0',sizeof(buf));int num;if((num=sock.rio_writeline(sock.sock, &offline, sizeof(offline), 0))<=0)::MessageBox(NULL,"下线请求失败","system error",MB_OK|MB_ICONERROR);closesocket(sock);return CPropertySheet::DestroyWindow();}

--------------------------------------------------------------------------------------------------------------

其余还有一些用例函数没有列出,例如添加,删除好友,在线上报线程用例等等,这些功能不难,再贴代码就显得更累赘了。