vc学习之服务器客户机通信

来源:互联网 发布:使命召唤14优化差 编辑:程序博客网 时间:2024/05/01 02:18

 

服 务 器 与 客 户 机 互 传 消 息


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

原创粉丝点击