本节介绍剩下的用例:个人信息修改用例、用户查询用例、客户信息传输用例、退出系统用例;
客户端中的个人信息修改用例步骤以及主要代码:
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();
}
--------------------------------------------------------------------------------------------------------------
其余还有一些用例函数没有列出,例如添加,删除好友,在线上报线程用例等等,这些功能不难,再贴代码就显得更累赘了。