本节介绍剩下的用例:个人信息修改用例、用户查询用例、客户信息传输用例、退出系统用例;
客户端中的个人信息修改用例步骤以及主要代码:
1)输入更改内容
2)本地格式校验
3)发送更改资料请求
4)返回反馈信息
5)更新用户资料命令
void CSetDlg::OnOK() { // TODO: Add extra validation here UpdateData(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; else if(m_strSex=="女") set.sex=0x02; else if(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); //刷新好友列表的自己 //待写 //更新LastMsg LastMsg.name=m_strName; LastMsg.sex=m_strSex; LastMsg.age=m_ByteAge; LastMsg.city=m_strCity; LastMsg.info=m_strInfo; } else if((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++; } } } else if((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(); }
--------------------------------------------------------------------------------------------------------------
其余还有一些用例函数没有列出,例如添加,删除好友,在线上报线程用例等等,这些功能不难,再贴代码就显得更累赘了。