韩冰 发表于 2005-1-26 01:16

服务器与客户机互传消息

<P>  </P>
<P>一、 服 务 器 程 序 </P>
<P>创 建 一 个 名 为“server" 的 项 目, 单 文 档 界 面。 </P>
<P>在serverview.h 中 加 入 代 码: </P>
<P>           #include “winsock.h" </P>
<P>      添 加 变 量: </P>
<P>            CSize       sizeTotal;// 控 制 滚 动 条 </P>
<P>            int   count;// 信 息 条 数 </P>
<P>            CString m_data;// 信 息 存 放 </P>
<P>            char    Hostname; </P>
<P>            char  Hostaddress;// 主 机IP 地 址 </P>
<P>            SOCKET      m_sock; </P>
<P>            HANDLE      m_hListenThread;// 线 程 </P>
<P>            BOOL  m_bInitialized;// 是 否 初 始 化 </P>
<P>            WSADATA     WSAData; </P>
<P>            BOOL  flag; </P>
<P>            SOCKADDR_IN saClnt; </P>
<P>            int   saClntLen; </P>
<P>            BOOL  Isconnect;// 是 否 连 接 </P>
<P>  </P>
<P>在serverview.cpp 中 重 载CServerView() 构 造 器, 创 建 并 绑 定 嵌 套 </P>
<P> 字: </P>
<P>      CServerView::CServerView() </P>
<P>{     // TOD add construction code here </P>
<P>      Isconnect=FALSE; </P>
<P>      flag=FALSE; </P>
<P>      sizeTotal.cy=350; </P>
<P>      sizeTotal.cx=300; </P>
<P>      m_hListenThread; </P>
<P>      count=5; </P>
<P>      int status; </P>
<P>      WSADATA wsaData; </P>
<P>   m_data=“initializing Windows Sockets DLL...."; </P>
<P>      if((status=WSAStartup(0x0101, &wsaData))==0) </P>
<P>      {     m_data +=“Succeeded"; </P>
<P>            m_bInitialized=TRUE; </P>
<P>      } </P>
<P>      else </P>
<P>      {     m_bInitialized=FALSE; </P>
<P>      } </P>
<P>      m_sock=socket(AF_INET,SOCK_DGRAM,0); </P>
<P>      m_data=“Creating socket...."; </P>
<P>      if(m_sock==INVALID_SOCKET) </P>
<P>      {     m_data +=“Failed"; </P>
<P>      } </P>
<P>      m_data +=“Succeeded"; </P>
<P>      m_data=“Binding socket...."; </P>
<P>      sockaddr_in sa; </P>
<P>      sa.sin_family=AF_INET; </P>
<P>      sa.sin_addr.S_un.S_addr=htonl(INADDR_ANY); </P>
<P>      sa.sin_port=htons(5050); </P>
<P>      if(bind(m_sock,(PSOCKADDR) </P>
<P>     &sa,sizeof(sa))==SOCKET_ERROR) </P>
<P>      {     m_data +=“Failed"; </P>
<P>  </P>
<P>            closesocket(m_sock); </P>
<P>      } </P>
<P>      m_data +=“Succeeded"; </P>
<P>      m_data=“Creating listener thread...."; </P>
<P>      unsigned long idThread; </P>
<P> m_hListenThread=CreateThread(NULL,0, </P>
<P>(LPTHREAD_START_ROUTINE)Listen, </P>
<P>(void        if(m_hListenThread) </P>
<P>      {     m_data +=“Succeeded"; </P>
<P>            m_data +=“Listening...."; </P>
<P>      } </P>
<P>      else </P>
<P>            m_data +=“Failed"; </P>
<P>} </P>
<P>  </P>
<P>在 析 构 函 数 中 完 成 必 需 的 清 除 操 作: </P>
<P>      CServerView:: ~CServerView() </P>
<P>{     if(m_bInitialized) </P>
<P>      WSACleanup(); </P>
<P>      closesocket(m_sock); </P>
<P>      if(m_hListenThread) </P>
<P>      ::TerminateThread(m_hListenThread,0); </P>
<P>} </P>
<P>  </P>
<P>定 义 接 收 和 处 理 消 息 的 线 程: </P>
<P>      long WINAPI Listen(CServerView *pView) </P>
<P>{     char msg=“"; </P>
<P>      int   nchar; </P>
<P>      SOCKADDR_IN saClnt; </P>
<P>      int saClntLen; </P>
<P>      while(1) </P>
<P>      { saClntLen=sizeof(saClnt); </P>
<P>        nchar=recvfrom(pView -&gt;m_sock,msg,1024,0, </P>
<P>(PSOCKADDR) &saClnt, &saClntLen); </P>
<P>        if(nchar&lt;0) </P>
<P>        {     pView -&gt;m_data + </P>
<P>             =“Error in recvfrom\n"; </P>
<P>        pView -&gt;InvalidateRect(NULL); </P>
<P>        } </P>
<P>        else </P>
<P>        {switch(msg) </P>
<P>        { </P>
<P>        case  ‘A': </P>
<P>        wsprintf(msg,“A:Client from %s attached\n", </P>
<P>               inet_ntoa(saClnt.sin_addr)); </P>
<P>        pView -&gt;m_data=msg; </P>
<P>        pView -&gt;flag=TRUE; </P>
<P>        pView -&gt;InvalidateRect(NULL); </P>
<P>        pView -&gt;Isconnect=TRUE; </P>
<P>        pView -&gt;saClnt=saClnt; </P>
<P>        pView -&gt;saClntLen=saClntLen; </P>
<P>        sendto(pView -&gt;m_sock,msg,1024,0,(PSOCKADDR) </P>
<P>        &saClnt,saClntLen); </P>
<P>        break; </P>
<P>  </P>
<P>        case ‘D': </P>
<P>        wsprintf(msg,“D: Client form %s detached\n", </P>
<P>                inet_ntoa(saClnt.sin_addr)); </P>
<P>        pView -&gt;m_data=msg; </P>
<P>        pView -&gt;flag=TRUE; </P>
<P>        pView -&gt;InvalidateRect(NULL); </P>
<P>        pView -&gt;Isconnect=FALSE; </P>
<P>       sendto(pView -&gt;m_sock,msg,1024,0,(PSOCKADDR) </P>
<P>       &saClnt,saClntLen); </P>
<P>        break; </P>
<P>  </P>
<P>        case ‘R': </P>
<P>        saClntLen=sizeof(saClnt); </P>
<P>        pView -&gt;m_data=msg; </P>
<P>        pView -&gt;flag=TRUE; </P>
<P>        pView -&gt;InvalidateRect(NULL); </P>
<P>        break; </P>
<P>  </P>
<P>        default: </P>
<P>        break; </P>
<P>        } </P>
<P>        } </P>
<P>  </P>
<P>      } </P>
<P>      return(0); </P>
<P>} </P>
<P>  </P>
<P>在 程 序 菜 单 项 中 添 加“ 本 机IP 地 址": </P>
<P>    void CServerView::OnIp() </P>
<P>{int WSAReturn; </P>
<P> WSAReturn=WSAStartup( 0x0101, &WSAData ); </P>
<P> if( WSAReturn == 0 ){ </P>
<P> gethostname( Hostname, 260 ); </P>
<P> struct hostent *pHostEnt; </P>
<P> pHostEnt = gethostbyname( Hostname); </P>
<P> if( pHostEnt != NULL ){ </P>
<P> wsprintf( Hostaddress, “ %d. %d. %d. %d", </P>
<P>( pHostEnt -&gt;h_addr_list & 0x00ff ), </P>
<P>( pHostEnt -&gt;h_addr_list & 0x00ff ), </P>
<P>( pHostEnt -&gt;h_addr_list & 0x00ff ), </P>
<P>( pHostEnt -&gt;h_addr_list & 0x00ff ) ); </P>
<P>    CString out; </P>
<P>    out.Format(Hostaddress); </P>
<P>    AfxMessageBox(out); </P>
<P>    } </P>
<P>      } </P>
<P>} </P>
<P>  </P>
<P>在 程 序 菜 单 中 添 加“ 发 送 消 息": </P>
<P>    void CServerView::OnSendmessage() </P>
<P>{// TOD Add your command handler code here </P>
<P>      char msg; </P>
<P>      Csend Sendmessage; </P>
<P>      if(Sendmessage.DoModal()==IDOK </P>
<P>    & &!Sendmessage.m_Message.IsEmpty()) </P>
<P>    { wsprintf(msg,“R: " +Sendmessage.m_Message); </P>
<P>    sendto(m_sock,msg,1024,0,(PSOCKADDR) </P>
<P>      &saClnt,saClntLen); </P>
<P>    m_data=Sendmessage.m_Message; </P>
<P>    flag=TRUE; </P>
<P>    InvalidateRect(NULL); </P>
<P>    } </P>
<P>} </P>
<P>  </P>
<P>为 发 送 消 息 项 添 加 一 个 对 话 框 的 类, 名 为send, 有 一 个 文 </P>
<P>本 框, 用 来 发 送 消 息, 并 为 文 本 框 添 加CString m_Message 变 量 </P>
<P>, 在ServerView.cpp 中 添 加 #include “send.h" </P>
<P>为 发 送 消 息 项 添 加 一 个 判 断 函 数: </P>
<P>     void CServerView::OnUpdateSendmessage(CCmdUI * </P>
<P>pCmdUI) </P>
<P>{// TOD Add your command update UI handler code here </P>
<P>      pCmdUI -&gt;Enable(FALSE); </P>
<P>      if(Isconnect) </P>
<P>      pCmdUI -&gt;Enable(TRUE); </P>
<P>} </P>
<P>  </P>
<P>再 窗 口 显 示 消 息: </P>
<P>      void CServerView::OnDraw(CDC * pDC) </P>
<P>{     if(flag) </P>
<P>      {sizeTotal.cy +=20; </P>
<P>       for(int j=65;j </P>
<P>TextOut(10,y,m_data); </P>
<P>            y +=20;} </P>
<P>      // TOD add draw code for native data here </P>
<P>} </P>
<P>  </P>
<P>在Project 中 点 击Settings 中 选 择Link 项 添 加wsock32.lib。 </P>
<P>----最 后 编 译 程 序, 就 可 以 得 到Server.exe 程 序。 </P>
<P>  </P>
<P>二、 客 户 机 程 序 </P>
<P>创 建 一 个 名 为“client" 的 项 目, 单 文 档 界 面。 </P>
<P>在clientview.h 中 加 入 代 码: </P>
<P>            #include “winsock.h" </P>
<P>    添 加 变 量: </P>
<P>            CString m_data; </P>
<P>            HANDLE      m_hListenThread; </P>
<P>            SOCKET      m_sock; </P>
<P>            SOCKADDR_IN m_saSrvr; </P>
<P>            BOOL  Isconnect; </P>
<P>            int   count; </P>
<P>            CSize       sizeTotal; </P>
<P>            BOOL  flag; </P>
<P>  </P>
<P>在 构 造 函 数 中 初 始 化 变 量: </P>
<P>      CClientView::CClientView() </P>
<P>{     // TOD add construction code here </P>
<P>      Isconnect=FALSE; </P>
<P>      sizeTotal.cy=350; </P>
<P>      sizeTotal.cx=300; </P>
<P>      flag=FALSE; </P>
<P>} </P>
<P>  </P>
<P>在 析 构 函 数 中 完 成 清 除 操 作, 代 码 如 上。 </P>
<P>在 菜 单 中 添 加“ 拨 号" 项: </P>
<P>      void CClientView::OnDial() </P>
<P>{// TOD Add your command handler code here </P>
<P>      count=5; </P>
<P>      if(m_bInitialized) </P>
<P>      {     AfxMessageBox(“Already dialing"); </P>
<P>            return;} </P>
<P>      Cdial dial; </P>
<P>    if(dial.DoModal()==IDOK </P>
<P>    & &!dial.m_HostAddress.IsEmpty()) </P>
<P>      {m_saSrvr.sin_family=AF_INET; </P>
<P>       m_saSrvr.sin_addr.S_un.S_addr=htonl </P>
<P>(INADDR_ANY); </P>
<P>       m_saSrvr.sin_addr.S_un.S_addr=inet_addr </P>
<P>(dial.m_HostAddress); </P>
<P>       m_saSrvr.sin_port=htons(5050); </P>
<P>       int status; </P>
<P>       WSADATA wsaData; </P>
<P>       m_data=“initializing Windows Sockets DLL...."; </P>
<P>       if((status=WSAStartup(0x0101, &wsaData))==0) </P>
<P>      {     m_data +=“Succeeded"; </P>
<P>            m_bInitialized=TRUE;} </P>
<P>      else </P>
<P>      {     m_bInitialized=FALSE;} </P>
<P>      m_sock=socket(AF_INET,SOCK_DGRAM,0); </P>
<P>      m_data=“Creating socket...."; </P>
<P>      if(m_sock==INVALID_SOCKET) </P>
<P>      {     m_data +=“Failed";} </P>
<P>      m_data +=“Succeeded"; </P>
<P>      m_data=“Binding socket...."; </P>
<P>      sockaddr_in sa; </P>
<P>      sa.sin_family=AF_INET; </P>
<P>      sa.sin_addr.S_un.S_addr=htonl(INADDR_ANY); </P>
<P>      sa.sin_port=htons(0); </P>
<P>      if(bind(m_sock,(PSOCKADDR) </P>
<P>     &sa,sizeof(sa))==SOCKET_ERROR) </P>
<P>      {     m_data +=“Failed"; </P>
<P>            closesocket(m_sock);} </P>
<P>      m_data +=“Succeeded"; </P>
<P>      m_data=“Creating listener thread...."; </P>
<P>      unsigned long idThread; </P>
<P>      m_hListenThread=CreateThread(NULL 0, </P>
<P>(LPTHREAD_START_ROUTINE)Listen, </P>
<P>(void *)this,0, &idThread); </P>
<P>      if(m_hListenThread) </P>
<P>      {     m_data +=“Succeeded"; </P>
<P>            m_data +=“Waiting....";} </P>
<P>      else </P>
<P>      m_data +=“Failed"; </P>
<P>      InvalidateRect(NULL); </P>
<P>      } </P>
<P>} </P>
<P>  </P>
<P>添 加 一 个 拨 号 对 话 框, 名 为dial, 有 一 个 文 本 框 用 来 写IP 地 </P>
<P> 址. 并 在clientview.cpp 中 添 加 代 码: </P>
<P>      #include dial.h </P>
<P>  </P>
<P>在 拨 号 项 添 加 一 个 判 断 函 数: </P>
<P>    void CClientView::OnUpdateDial(CCmdUI * </P>
<P>pCmdUI) </P>
<P>{// TOD Add your command update UI handler code here </P>
<P>      pCmdUI -&gt;Enable(TRUE); </P>
<P>      if(Isconnect) </P>
<P>      pCmdUI -&gt;Enable(FALSE); </P>
<P>} </P>
<P>  </P>
<P>添 加 接 收 与 发 送 消 息 的 线 程: </P>
<P>      long WINAPI Listen(CClientView *pView) </P>
<P>{     char msg; </P>
<P>      pView -&gt;m_data=“Sending ATTACH command"; </P>
<P>      pView -&gt;InvalidateRect(NULL); </P>
<P>      wsprintf(msg,“A: "); </P>
<P>     sendto(pView -&gt;m_sock,msg,1024,0,(PSOCKADDR) </P>
<P>     &pView -&gt;m_saSrvr,sizeof(pView -&gt;m_saSrvr)); </P>
<P>      int saSrvrLen ,nchar; </P>
<P>      while(1) </P>
<P>      {saSrvrLen=sizeof(pView -&gt;m_saSrvr); </P>
<P>      nchar=recvfrom(pView -&gt;m_sock,msg,1024,0, </P>
<P>   (PSOCKADDR) &pView -&gt;m_saSrvr, &saSrvrLen); </P>
<P>      if(nchar&lt;0) </P>
<P>     {    pView -&gt;m_data= </P>
<P>             “Error in recvform"; </P>
<P>      pView -&gt;InvalidateRect(NULL);} </P>
<P>      else </P>
<P>     { pView -&gt;m_data=msg; </P>
<P>                  pView -&gt;Isconnect=TRUE; </P>
<P>                  pView -&gt;flag=TRUE; </P>
<P>                  pView -&gt;InvalidateRect(NULL); </P>
<P>            } </P>
<P>      } </P>
<P>      return(0); </P>
<P>} </P>
<P>  </P>
<P>同 主 程 序 一 样 做 一 个 发 送 消 息 项, 代 码 如 上。 </P>
<P>显 示 程 序 也 与 主 程 序 一 样, 代 码 如 上。 </P>
<P>在Project 中 点 击Settings 中 选 择Link 项 添 加wsock32.lib。 </P>
<P>编 译 程 序 便 可 得 到client.exe 程 序。 </P>
<P>----server.exe 和 client.exe 做 完 后, 就 可 以 在 具 有 TCP/IP 协 议 </P>
<P> 下 的 网 络 中 执 行。</P>
页: [1]
查看完整版本: 服务器与客户机互传消息