MFC下的网络编程(3)CS结构信息转发器的实现

服务器端

MFC下的网络编程(3)CS结构信息转发器的实现

        CListenSocket  m_listenSocket; //监听套接字

点击启动服务按键
        //创建监听套接字,激发FD_ACCEPT事件,默认端口5088
        BOOL bFlag=m_listenSocket.Create(5088,SOCK_STREAM,FD_ACCEPT);
        m_listenSocket.Listen(1)

在OnAccept()函数中
        //侦听到连接请求,调用Accept函数
        CNewSocketpSocket = new CNewSocket();
        if(Accept(*pSocket)) //接受连接
        {
         pSocket->AsyncSelect(FD_READ);     //有读事件的时候,Socket中的OnReceive事件就会触发
         m_pSocket=pSocket; //记录当前通信Socket
        }
        else
            delete pSocket;
        CAsyncSocket::OnAccept(nErrorCode);

在OnReceive()函数中
        m_nLength=Receive(m_szBuffer,sizeof(m_szBuffer),0);
        // 直接转发消息
        AsyncSelect(FD_WRITE);                //触发OnSend函数
        CAsyncSocket::OnReceive(nErrorCode);

在OnSend()函数中,发送接收到的数据
        char m_sendBuffer[4096];       //消息缓冲区
        memcpy(m_sendBuffer,"服务器转发:",24);
        strncat(m_sendBuffer,m_szBuffer,m_nLength);
        Send(m_sendBuffer,sizeof(m_sendBuffer));    //发送数据
        AsyncSelect(FD_READ);    //触发OnReceive函数
        CAsyncSocket::OnSend(nErrorCode);

客户端

MFC下的网络编程(3)CS结构信息转发器的实现

        CClientSocket m_clientSocket;

点击连接按键,执行OnConnect函数

        m_clientSocket.ShutDown(2);
        m_clientSocket.m_hSocket=INVALID_SOCKET;
        m_clientSocket.m_bConnected=FALSE;

         CAddrDlg m_Dlg
        m_szPort=5088;//默认端口5088
        if (m_Dlg.DoModal()==IDOK && !m_Dlg.m_Addr.IsEmpty())    //填写IP地址,点击确认键
         {
            memcpy(m_szServerAdr,m_Dlg.m_Addr,sizeof(m_szServerAdr)); 
           //建立计时器,每1秒尝试连接一次,直到连上或TryCount>10 
           SetTimer(1,1000,NULL); 
           TryCount=0;
          }
MFC下的网络编程(3)CS结构信息转发器的实现

在定时器处理函数中
        BOOL bFlag=m_clientSocket.Create(0,SOCK_STREAM,FD_CONNECT);      //创建套接字
        m_clientSocket.Connect(m_szServerAdr,m_szPort); //连接服务器
        TryCount++; //连接次数加1
        if (TryCount >=10 || m_clientSocket.m_bConnected) //如果已经连接或连接超时
        {
         KillTimer(1); //关闭定时器
         if (TryCount >=10) //连接超时
           {
             AfxMessageBox("连接失败!");
             GetDlgItem(IDC_CONNECT)->EnableWindow(true);
           }
        return;
        }

至此连接结束,接下来就是发送数据,填好发送的信息后,点击发送按键,执行OnSend函数
        if (m_clientSocket.m_bConnected)  //先检查是否已经连接
         {    
               //获取用户数据的待发送信息
           m_clientSocket.m_nLength=m_MsgS.GetWindowText(m_clientSocket.m_szBuffer,                                      sizeof(m_clientSocket.m_szBuffer));
           //触发Socket的OnSend函数
           m_clientSocket.AsyncSelect(FD_WRITE);
          }
       在CClientSocketCTransClientDlg这两个类中都有OnConnect、OnSend函数,前面说的都是CTransClientDlg这个类中的函数。下面用到的是CClientSocket中的
      AsyncSelect括号内的参数是诸如FD_CONNECT、FD_WRITE、FD_READ这些常量 
 。      
      AsyncSelect(FD_READ)投递一个“读“的事件,准备接收,如果有读事件的时候,那么OnReceive事件就会触发, 
如果传入FD_WRITE就投了一个“写”事件,那么当发送数据的时候,你的OnSend事件就会触发。可以用|来表示需要监听多个事件。 
在触发的OnSend函数中发送数据
           Send(m_szBuffer,m_nLength,0);//发送数据
           m_nLength=0;
           memset(m_szBuffer,0,sizeof(m_szBuffer));//清除缓冲区数据
           //继续提请一个"读"的网络事件,如果有读事件的时候,那么OnReceive事件就会触发
           AsyncSelect(FD_READ);
           CAsyncSocket::OnSend(nErrorCode);

因为在之前调用了AsyncSelect(FD_READ),当收到服务器信息后,就会执行OnReceive函数
           m_nLength=Receive(m_szBuffer,sizeof(m_szBuffer),0);   //接收数据
           pDlg->m_MsgR.InsertString(0,m_szBuffer);//列表框添加接收的数据
           memset(m_szBuffer,0,sizeof(m_szBuffer));//清除缓冲区数据