首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

自持即时通信系统:socket网络编程(5)

2013-10-08 
自制即时通信系统:socket网络编程(5)从本节开始,从IM的功能出发,以及代码展示来实现IM客户端:从第一个用例

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

从本节开始,从IM的功能出发,以及代码展示来实现IM客户端:
从第一个用例开始:注册
注册按钮是放置在登陆界面上的,笔者的登陆界面展示如下:

自持即时通信系统:socket网络编程(5)

单击注册按钮后,出现如下界面:

自持即时通信系统:socket网络编程(5)

如图所示,登陆界面是程序的主对话框,客户端的注册框的任务是:
1)建立客户端与服务端链接//这一步在CRegister::OnInitDialog()中执行
2)填写注册信息
3)检查信息格式//此步以及后面的步骤在CRegister::OnOK()中执行
4)发送注册包
5)接受服务端的反馈包
8)断开与服务端的链接
根据上面的流程,当填好注册信息后,主要执行代码如下:

BOOL CRegister::OnInitDialog() {CDialog::OnInitDialog();// TODO: Add extra initialization here//设置默认性别((CButton *)GetDlgItem(IDC_RADIO3))->SetCheck(TRUE);//选上sex=0x04;//添加代码--〉向服务器申请登陆BYTE *pIP;//获取IP控件AddressCString strIP;DWORD dwIP;CWnd *pWnd=GetParent();((CLoggingDlg *)pWnd)->m_Address.GetAddress(dwIP);pIP = (unsigned   char*)&dwIP;strIP.Format( "%u.%u.%u.%u ",*(pIP+3), *(pIP+2), *(pIP+1), *pIP);//链接extern CTCPSocket sock;if(sock.SetupTCPClientSocket(strIP, ((CLoggingDlg *)pWnd)->m_strPort)<0){::MessageBox(NULL,"socket() or connect() failed","system error",MB_OK|MB_ICONERROR);}else//链接成功{sock.rio_readinitb(sock.rio, sock.sock);}return TRUE;  // return TRUE unless you set the focus to a control              // EXCEPTION: OCX Property Pages should return FALSE}void CRegister::OnOK() {// 本地数据检验与处理UpdateData(TRUE);if(m_ByteAge>130)::MessageBox(NULL,"年龄范围在0-130之间","错误信息",MB_OK|MB_ICONERROR);if(m_strPass!=m_strRePass)::MessageBox(NULL,"两次密码输入不一致","错误信息",MB_OK|MB_ICONERROR);m_strName.TrimLeft();m_strName.TrimRight();//发送数据extern CTCPSocket sock;cln_register reg;reg.magic=0x54;reg.flags=0x02;sprintf(reg.name,"%s",m_strName);sprintf(reg.pass,"%s",m_strPass);sprintf(reg.city,"%s",m_strCity);reg.age=m_ByteAge;reg.sex=sex;sprintf(reg.info,"%s",m_strInfo);int num;if((num=sock.rio_writeline(sock.sock, ?, sizeof(reg), 0))<0)::MessageBox(NULL,"发送注册消息失败","system error",MB_OK|MB_ICONERROR);//接受数据char buf[88];int size=sock.rio_readlineb(sock.rio, buf, sizeof(buf));serv_register *serv_reg=(serv_register *)buf;if(serv_reg->magic==0x55 && serv_reg->flags==0x02){CString str="注册成功,id:";str += serv_reg->id;str += "密码:";str += serv_reg->pass;::MessageBox(NULL,str,"system error",MB_OK);closesocket(sock);//关闭TCP套接字CDialog::OnOK();}else{::MessageBox(NULL,"注册失败,请重新注册","system error",MB_OK|MB_ICONERROR);}}

 
以上就是注册用例了,可以看出明显的缺陷是:每次注册都会链接一次服务器,注册结束后直接回到登陆界面,关于注册失败也没有采取保留措施,导致用户友好性不是很好,不过这些都可以改善,读者有兴趣可以试一试;

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

既然讲了注册,下面就将登陆一并讲了吧:
客户端的登陆任务步骤如下:
1)建立客户端与服务端链接
2)输入登录信息
3)本地校验输入信息格式错误
4)发送登录请求
5)接受服务端的反馈包
6)分析包:登陆成功或失败(成功则进入好友界面,接受好友信息)
根据上面的流程,当填好登陆信息后,主要执行代码如下:

BOOL CLoggingDlg::OnInitDialog() {CDialog::OnInitDialog();// TODO: Add extra initialization herem_ButtonCheckPort.SetCheck(BST_CHECKED);//默认自动获取portif(m_ButtonCheckPort.GetCheck()){m_EditPort.EnableWindow(FALSE);}m_ButtonIp.SetCheck(BST_CHECKED);//使用默认IPif(m_ButtonIp.GetCheck()){m_Address.EnableWindow(FALSE);}//设置IP默认值CString strIP = "127.0.0.1 ";DWORD  dwIP = inet_addr(strIP);BYTE *pIP = (BYTE*)&dwIP;m_Address.SetAddress(*pIP, *(pIP+1), *(pIP+2), *(pIP+3));return TRUE;  // return TRUE unless you set the focus to a control              // EXCEPTION: OCX Property Pages should return FALSE}void CLoggingDlg::OnCheckPort() {// TODO: Add your control notification handler code hereif(m_ButtonCheckPort.GetCheck()){m_EditPort.EnableWindow(FALSE);}elsem_EditPort.EnableWindow(TRUE);}void CLoggingDlg::OnCheckIp() {// TODO: Add your control notification handler code hereif(m_ButtonIp.GetCheck()){m_Address.EnableWindow(FALSE);}elsem_Address.EnableWindow(TRUE);}

void CLoggingDlg::OnOK() { // TODO: 本地校验 this->UpdateData(TRUE); if((strcmp(this->m_strUserId,"")==0) || (strcmp(this->m_strPassword ,"")==0)) {  ::MessageBox(NULL,"用户名或口令不能为空!","错误信息",MB_OK|MB_ICONERROR); }  else  {   this->UpdateData(TRUE);   //添加代码--〉向服务器申请登陆   BYTE *pIP;//获取IP控件Address   CString strIP;   DWORD dwIP;   m_Address.GetAddress(dwIP);   pIP = (unsigned   char*)&dwIP;   strIP.Format( "%u.%u.%u.%u ",*(pIP+3), *(pIP+2), *(pIP+1), *pIP);   //生成链接socket   extern CTCPSocket sock;   //extern rio_t rio;      if(sock.SetupTCPClientSocket(strIP, m_strPort)<0)   {    ::MessageBox(NULL,"socket() or connect() failed","system error",MB_OK|MB_ICONERROR);   }    else//链接成功    {     sock.rio_readinitb(sock.rio, sock.sock);     cln_log log;     log.magic=0x54;     log.flags=0x01;     sprintf(log.userid,"%s",m_strUserId);     sprintf(log.password,"%s",m_strPassword);     char buf[10];     memset(buf,'\0',sizeof(buf));     int num;     if((num=sock.rio_writeline(sock.sock, &log, sizeof(log), 0))<=0)      ::MessageBox(NULL,"rio_writen() failed","system error",MB_OK|MB_ICONERROR);

     int size=sock.rio_readlineb(sock.rio, buf, sizeof(buf));

     if(size>0)     {      header *servlog =(header *)buf;      if((servlog->magic==0x55) && (servlog->flags==0x01))       //登录成功       CDialog::OnOK();//打开好友聊天界面对话框      else       if((servlog->magic==0x54) && (servlog->flags==0x01))        ::MessageBox(NULL,"登录失败","system error",MB_OK|MB_ICONERROR);       else        ::MessageBox(NULL,"数据包不在服务范围内","system error",MB_OK|MB_ICONERROR);     }    }  }}

 

热点排行