基于IP多播组讨论会实例第3部分

   在工作线程创建发送和接收套接字,设置他们的属性,将接受套接字加入到会议组,之后进入无限循环再m_sRead套接字上读取到来的UDP封包,然后调用DispatchMSG可以处理这些封装包。DispatchMsg处理来自组中其他成员的消息,发送针对这些消息的响应,通知窗口。下面就是实现的代码.
// 处理到来的消息,将它们分发到主窗口
void CGroupTalk::DispatchMsg(GT_HDR *pHeader, int nLen)
{
       if(pHeader->gt_type == MT_JION)      // 新用户加入
       {    
              // 向新加入用户发送自己的用户信息
              char buff[sizeof(GT_HDR)] = { 0 };
              GT_HDR *pSend = (GT_HDR*)buff;
              strncpy(pSend->szUser, m_szUser, 15);     
              pSend->gt_type = MT_MINE;
              pSend->nDataLength = 0;
              Send(buff, sizeof(GT_HDR), pHeader->dwAddr);
       }
       else if(pHeader->gt_type == MT_MINE)
       {    
              // 是否来自自己,如果是,则不处理
              if(strcmp(pHeader->szUser, m_szUser) == 0)
                     return;
              // 为简单起见,把在线用户当成新加入用户处理
              pHeader->gt_type = MT_JION;
       }
 
       // 通知主窗口处理
       ::SendMessage(m_hNotifyWnd, WM_GROUPTALK, 0, (LPARAM)pHeader);
}
说明:
1.Send(buff, sizeof(GT_HDR), pHeader->dwAddr);
 
 第一个参数buff是一个内存块,将它轻质类型转换成用于存储GT_HDR结构数据的地方,这个GT_HDR的内存块就是所谓的“包”。
2.::SendMessage(m_hNotifyWnd, WM_GROUPTALK, 0, (LPARAM)pHeader);
 
发送一个WM_GROUPTALK消息到窗口函数,其中第四个参数是消息的WM_GROUPTALK的额外信息,也就是关于GT_HDR包的信息。
最后,提供给用户的发送消息函数SendText的实现代码如下:
 
int CGroupTalk::Send(char *szText, int nLen, DWORD dwRemoteAddr)
{
       // 发送UDP封包
       sockaddr_in dest;
       dest.sin_family = AF_INET;
       dest.sin_addr.S_un.S_addr = dwRemoteAddr;
       dest.sin_port = ::ntohs(GROUP_PORT);
       return ::sendto(m_sSend, szText, nLen, 0, (sockaddr*)&dest, sizeof(dest));
}
程序界面部分:
BOOL __stdcall DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
       switch(uMsg)
       {    
       case WM_INITDIALOG:
              {
                     // 创建CGroupTalk对象
                     g_pTalk = new CGroupTalk(hDlg, ::inet_addr("234.5.6.7"));
                     ::CheckDlgButton(hDlg, IDC_SELGROUP, 1);
                     ::SendMessage(hDlg, WM_SETICON, ICON_SMALL,
                                   (long)::LoadIcon(::GetModuleHandle(NULL), (LPCTSTR)IDI_MAIN));
              }
              break;
 
       case WM_GROUPTALK:
              {
                     // 处理CGroupTalk对象发来的消息
                     if(wParam != 0)
                            ::MessageBox(hDlg, (LPCTSTR)lParam, "出错!", 0);
                     else
                            HandleGroupMsg(hDlg, (GT_HDR*)lParam);
              }
              break;
 
       case WM_COMMAND:
              switch(LOWORD(wParam))
              {
              case IDC_SEND:          // 用户按下发送消息按钮
                     {
                            // 取得要发送的消息
                            char szText[1024];
                            int nLen = ::GetWindowText(::GetDlgItem(hDlg, IDC_SENDMSG), szText, 1024);
                            if(nLen == 0)
                                   break;
 
                            // 是面向组,还是面向用户?
                            BOOL bToAll = ::IsDlgButtonChecked(hDlg, IDC_SELGROUP);
                            DWORD dwAddr;
                            if(bToAll)
                            {
                                   dwAddr = 0;
                            }
                            else
                            {
                                   int nIndex = ::SendDlgItemMessage(hDlg, IDC_USERS, CB_GETCURSEL, 0, 0);
                                   if(nIndex == -1)
                                   {
                                          ::MessageBox(hDlg, "请选择一个用户!", "GroupTalk", 0);
                                          break;
                                   }
                                   // 取得用户IP地址
                                   dwAddr = ::SendDlgItemMessage(hDlg, IDC_USERS, CB_GETITEMDATA, nIndex, 0);
                            }
                            // 发送消息
                            if(g_pTalk->SendText(szText, nLen, dwAddr) == nLen)
                                          ::SetWindowText(::GetDlgItem(hDlg, IDC_SENDMSG), "");
                     }
                     break;
 
              case IDC_CLEAR:         // 用户按下清除按钮
                            ::SendDlgItemMessage(hDlg, IDC_RECORD, LB_RESETCONTENT, 0, 0);
                     break;
 
              case IDCANCEL:          // 用户关闭程序
                     {
                            delete g_pTalk;
                            ::EndDialog (hDlg, IDCANCEL);
                     }
                     break;
              }
              break;
       }
       return 0;
}
说明:
1.          HandleGroupMsg(hDlg, (GT_HDR*)lParam);
所有的CGroupTalk发送来的消息都由HandleGroupMsg函数来处理,它将消息通知个用户,维护组员的列表,具体代码如下:
oid HandleGroupMsg(HWND hDlg, GT_HDR *pHeader)
{
       switch(pHeader->gt_type)
       {
       case MT_JION:            // 新用户加入
              {
                     // 显示给用户
                     char szText[56];
                     wsprintf(szText, " 用户:《%s》加入!", pHeader->szUser);
                     ::SetWindowText(::GetDlgItem(hDlg, IDC_SYSMSG), szText);
 
                     // 将新用户信息添加到列表框中
                     int nCurSel = ::SendDlgItemMessage(hDlg, IDC_USERS, CB_GETCURSEL, 0, 0);
                     int nIndex = ::SendDlgItemMessage(hDlg, IDC_USERS, CB_ADDSTRING, 0, (long)pHeader->szUser);
                     ::SendDlgItemMessage(hDlg, IDC_USERS, CB_SETITEMDATA, nIndex, (long)pHeader->dwAddr);
                     if(nCurSel == -1)
                            nCurSel = nIndex;
                     ::SendDlgItemMessage(hDlg, IDC_USERS, CB_SETCURSEL, nCurSel, 0);
              }
              break;
 
       case MT_LEAVE:          // 用户离开
              {
                     // 显示给用户
                     char szText[56];
                     wsprintf(szText, " 用户:《%s》离开!", pHeader->szUser);
                     ::SetWindowText(::GetDlgItem(hDlg, IDC_SYSMSG), szText);
 
                     // 将离开的用户从列表框中移除
                     int nCount = ::SendDlgItemMessage(hDlg, IDC_USERS, CB_GETCOUNT, 0, 0);
                     for(int i=0; i<nCount; i++)
                     {
                            int nIndex = ::SendDlgItemMessage(hDlg, IDC_USERS, CB_FINDSTRING, i, (long)pHeader->szUser);
                            if((DWORD)::SendDlgItemMessage(hDlg, IDC_USERS, CB_GETITEMDATA, nIndex, 0) == pHeader->dwAddr)
                            {
                                   ::SendDlgItemMessage(hDlg, IDC_USERS, CB_DELETESTRING, nIndex, 0);
                                   break;
                            }
                     }    
              }
              break;
 
       case MT_MESG:           // 用户发送消息
              {
                     char *psz = pHeader->data();
                     psz[pHeader->nDataLength] = '/0';
                     char szText[1024];
                     wsprintf(szText, "【%s 说】", pHeader->szUser);
                     strncat(szText, psz, 1024 - strlen(szText));
                     ::SendDlgItemMessage(hDlg, IDC_RECORD, LB_INSERTSTRING, 0, (long)szText);
              }
              break;
       }
}
代码分析结束,陆续会将一些细节问题进行讨论,然后发布。
 
 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值