CAsyncSocket网络编程(MFC)

随着计算机网络化的深入,计算机网络编程在程序设计的过程中变得日益重要。由于C++语言对底层操作的优越性,许多文章都曾经介绍过用VC++进行Socket编程的方法。但由于都是直接利用动态连接库wsock32.dll进行操作,实现比较繁琐。其实,VC++的MFC类库中提供了CAsyncSocket这样一个套接字类,用他来实现Socket编程,是非常方便的。

---- 本文将用一个Echo例程来介绍CAsyncSocket类的用法。

---- 一. 客户端

---- 1. 创建一个Dialog Based项目:CSockClient。

---- 2. 设计对话框

---- 去掉Ok和Cancle两个按钮,增加ID_Connect(连接)、ID_Send(发送)、ID_Exit(关闭)按钮,增加ListBox控件IDC_LISTMSG和Edit控件IDC_EDITMSG,并按下表在ClassWizard中为CCSockClientDlg类添加变量。 Control ID 
Type Member 
IDC_EDITMSG 
CEdit m_MSGIDC_LISTMSG 
ClistBox 
m_MSGS

---- 3. CAsyncSocket类用DoCallBack函数处理MFC消息,当一个网络事件发生时,DoCallBack函数按网络事件类型:FD_READ、FD_WRITE、FD_ACCEPT、FD_CONNECT分别调用OnReceive、OnSend、OnAccept、OnConnect函数。由于MFC把这些事件处理函数定义为虚函数,所以要生成一个新的C++类,以重载这些函数,做法如下:

---- 以Public方式继承CAsyncSocket类,生成新类MySock;

---- 为MySock类添加虚函数OnReceive、OnConnect、OnSend

---- 4. 在MySock.ccp中添加以下代码 #include "CSockClient.h"#include "CSockClientDlg.h"

---- 5. 在MySock.h中添加以下代码 public: BOOL m_bConnected; 
//是否连接 UINT m_nLength; 
//消息长度 char m_szBuffer[4096]; 
//消息缓冲区

---- 6. 在MySock.ccp中重载各函数 MySock::MySock()

{

  m_nLength=0; 
  memset(m_szBuffer,0,sizeof(m_szBuffer)); 
  m_bConnected=FALSE;

}

MySock::~MySock()


  //关闭套接字if(m_hSocket!=INVALID_SOCKET) 
  Close();

}
void MySock::OnReceive(int nErrorCode)


m_nLength=Receive(m_szBuffer,sizeof(m_szBuffer),0); 
//下面两行代码用来获取对话框指针

CCSockClientApp* pApp=(CCSockClientApp*)AfxGetApp(); 
CCSockClientDlg* pDlg=(CCSockClientDlg*)pApp- >m_pMainWnd; 
pDlg- >m_MSGS.InsertString(0,m_szBuffer);

memset(m_szBuffer,0,sizeof(m_szBuffer)); 
CAsyncSocket::OnReceive(nErrorCode)
;

}

void MySock::OnSend(int nErrorCode)


Send(m_szBuffer,m_nLength,0); m_nLength=0; 
memset(m_szBuffer,0,sizeof(m_szBuffer)); 
//继续提请一个“读”的网络事件,接收Server消息AsyncSelect(FD_READ); 
CAsyncSocket::OnSend(nErrorCode);

}

void MySock::OnConnect(int nErrorCode)


if (nErrorCode==0)


  m_bConnected=TRUE; 
  CCSockClientApp* pApp=(CCSockClientApp*)AfxGetApp(); 
  CCSockClientDlg* pDlg=(CCSockClientDlg*)pApp- >m_pMainWnd; 
  memcpy(m_szBuffer,"Connected to ",13); 
  strncat(m_szBuffer,pDlg- >m_szServerAdr, 
  sizeof(pDlg- >m_szServerAdr)); 
  pDlg- >m_MSGS.InsertString(0,m_szBuffer); 
  AsyncSelect(FD_READ); 
////提请一个“读”的网络事件,准备接收


CAsyncSocket::OnConnect(nErrorCode);

}

---- 7. 新建对话框IDD_Addr,用来输入IP地址和Port;生成新类CAddrDlg。增加两个Edit控件:IDC_Addr、IDC_Port按下表在ClassWizard中为CAddrDlg类添加变量。 Control ID Type MemberIDC_Addr CString m_AddrIDC_Port Int m_Port

---- 8. 在CSockClientDlg.ccp中添加代码 #include "AddrDlg.h"protected: int TryCount; 
MySock m_clientSocket; 
UINT m_szPort;public: char m_szServerAdr[256];

---- 9. 双击IDD_CSOCKCLIENT_DIALOG对话框中的“连接”按钮,添加以下代码

void CCSockClientDlg::OnConnect()


m_clientSocket.ShutDown(2); 
m_clientSocket.m_hSocket=INVALID_SOCKET; 
m_clientSocket.m_bConnected=FALSE; 
CAddrDlg m_Dlg; //默认端口1088m_Dlg.m_Port=1088; 
if (m_Dlg.DoModal()==IDOK && !m_Dlg.m_Addr.IsEmpty())


memcpy(m_szServerAdr,m_Dlg.m_Addr,sizeof(m_szServerAdr)); 
m_szPort=m_Dlg.m_Port; //建立计时器,每1秒尝试连接一次,直到连上或TryCount>10SetTimer(1,1000,NULL);
TryCount=0;

}

}

---- 10. 添加Windows消息WM_TIMER响应函数OnTimer

void CCSockClientDlg::OnTimer(UINT nIDEvent)


if (m_clientSocket.m_hSocket==INVALID_SOCKET)


BOOL bFlag=m_clientSocket.Create(0,SOCK_STREAM,FD_CONNECT); 
  if(!bFlag)

  {

    AfxMessageBox("Socket Error!"); 
    m_clientSocket.Close(); 
    PostQuitMessage(0); 
  return; 
  }


m_clientSocket.Connect(m_szServerAdr,m_szPort); 
TryCount++; 
if (TryCount >=10 || m_clientSocket.m_bConnected)


KillTimer(1); 
if (TryCount >=10) AfxMessageBox("Connect Failed!"); 
return;


CDialog::OnTimer(nIDEvent);

}

---- 11. 双击IDD_CSOCKCLIENT_DIALOG对话框中的“发送”按钮,添加以下代码

void CCSockClientDlg::OnSend()


if (m_clientSocket.m_bConnected) 
{

m_clientSocket.m_nLength=m_MSG.GetWindowText(m_clientSocket.m_szBuffer, sizeof(m_clientSocket.m_szBuffer)); 
m_clientSocket.AsyncSelect(FD_WRITE); 
m_MSG.SetWindowText("");

}

}

---- 12. 双击IDD_CSOCKCLIENT_DIALOG对话框中的“关闭”按钮,添加以下代码 void CCSockClientDlg::OnExit() { 
//关闭Socketm_clientSocket.ShutDown(2); //关闭对话框EndDialog(0); }

----12.运行此项目,连接时输入主机名或IP均可,CAsyncSocket类会自动处理。

----二. 服务端

----Server端的编程与Client端的类似,下面主要介绍他的Listen及Accept函数

----1. 建立一个CNewSocket类,重载CAsyncSocket类的OnReceive、OnSend函数,

如何进行信息的显示和发送可以参考Client程序。本例中采用将收到信息原封不动

发回的方法来实现Echo功能,代码如下CNewSocket::OnReceive(int nErrorCOde){ 
m_nLength=Receive(m_szBuffer,sizeof(m_szBuffer),0); 
// 直接转发消息AsyncSelect(FD_WRITE);}CNewSocket::OnSend(int nErrorCode){ Send(m_szBuffer,m_nLength,0);}

----2. 建立一个CMyServerSocket类,重载CAsyncSocket类的OnAccept函数代码如下

----在MyServerSocket.h中声明变量public::CNewSocket* m_pSocket;
void CMyServerSocket::OnAccept(int nErrorCode)


//侦听到连接请求,调用Accept函数 
CNewSocket* pSocket = new CNewSocket(); 
if (Accept(*pSocket))


pSocket- >AsyncSelect(FD_READ);
m_pSocket=pSocket; 
}

else 
delete pSocket;

}

----3. 为对话框添加一个“侦听”按钮,添加如下代码

----在CsockServerDlg.ccp中声明变量

public: CMyServerSocket m_srvrSocket;
void CCSockServerDlg::OnListen()

{

if(m_srvrSocket.m_hSocket==INVALID_SOCKET)


  BOOL bFlag=m_srvrSocket.Create 
  (UserPort,SOCK_STREAM,FD_ACCEPT); 
  if (!bFlag)

  {

   AfxMessageBox(“Socket Error!”); 
  M_srvrSocket.Close(); 
  PostQuitMessage(0); 
  Return;

  }

}
//“侦听”成功,等待连接请求

if (!m_srvrSocket。Listen(1))


  int nErrorCode = m_srvrSocket.GetLastError(); 
  if (nError!=WSAEWOULDBLOCK) 
  { 
  AfxMessageBox(“Socket Error!”); 
  M_srvrSocket.Close(); 
  PostQuitMessage(0); 
  Return; 
  }

}

}

----4. 目前程序只能实现Echo功能,将信息原封不动的转发,若能将Accept中由CNewSocket* pSocket = new CNewSocket();得到的Socket指针存入一个CList或一个数组中,便像Client端那样,对所有的连接进行读写控制。

----三. 总结

----CAsyncSocket类为我们使用Socket提供了极大方便。建立Socket的WSAStartup过程和bind过程被简化成为Create过程,IP地址类型转换、主机名和IP地址转换的过程中许多复杂的变量类型都被简化成字符串和整数操作,特别是CAsyncSocket类的异步特点,完全可以替代繁琐的线程操作。MFC提供了大量的类库,我们若能灵活的使用他们,便会大大提高编程的效率

时间: 2024-10-07 06:52:39

CAsyncSocket网络编程(MFC)的相关文章

MFC快速网络编程启示录

好久没有使用MFC实现网络编程啦.如何实现MFC网络编程呢? 随着计算机网络化的深入,计算机网络编程在程序设计的过程中变得日益 重要.由于C++语言对底层操作的优越性,许多文章都曾经介绍过用VC++ 进行Socket编程的方法.但由于都是直接利用动态连接库wsock32.dll进 行操作,实现比较繁琐.其实,VC++的MFC类库中提供了CAsyncSocket这 样一个套接字类,用他来实现Socket编程,是非常方便的. 本文将用一个Echo例程来介绍CAsyncSocket类的用法. 一. 客

《MFC网络编程》学习日记3

一个基于UDP的网络通迅程序:整个例子有两个程序组成,一个发送数据,另一个程序接收数据后,完成绘图工作.本文程序运行效果图如下: 一.发送程序首先建立数据发送程序( Fason) .一共发送四个数据:圆心的 X坐标.圆心的 Y坐标.圆半径 R.圆的颜色.它的实现主要如下:void CFasonDlg::OnSend(){UpdateData(TRUE);CString m_Getstring;this->m_Cob.GetLBText(m_Cob.GetCurSel(),m_Getstring)

MFC第二节-网络编程

使用socket编程. 一.需要套接字库.要知道申请的套接字库的版本,版本号利用WORD类型表示:MAKEWORD,加载后要检查得到的是否是申请的版本. 二.需要创建套接字.套接字SOCKET结构体. 三.SOCKET对象和SOCKADDR套接字地址绑定,对TCP\IP编程中,可以用SOCKADDR_IN代替SOCKADDR(都是代表地址空间).SOCKADDR_IN包括sin_family:地址族,对于IP地址一直是AF_INET,sin_port是按网络字节顺序表示的端口地址,sin_add

MFC——10.网络编程基础

Lesson10:网络编程基础 网络编程是计算机编程的一个重要分支,是网络通信的基础,网络编程主要用到了Windows系统系统提供的socket.网络通信又分为基于TCP和基于UDP两种.本文主要讲解基于TCP和UDP的网络编程基础知识. 1.      基于TCP的socket编程 1.1  TCP服务器 #include <winsock2.h> #include <stdio.h> //#include <iostream> #pragma comment(lib

VC++6.0网络编程Socket编程(转)

从csdn上下载的该软件的教程: 作为一个初学者,深感Socket编程入门的困难,但当把一些问题弄懂之后,回过头来看以前遇到的一些问题,才发现 Socket编程其实并没有那么复杂.接下来我就把我遇到的一些困难讲述下,并补上解决的办法. 首先我们要想实现一个简单的点对点网络通信,就应该有一个客户和一个服务器 我们先来做客户端.先按照如下图所示建立好客户对话框模块: 首先创建一个基于MFC AppWizard[EXE] 工程,工程名为Socket__002 (这里是以我的工程名为准,你们也可以自己命

VC++网络编程学习笔记

Visual C++网络编程是指用户使用MFC类库(微软基础类库)在VC编译器中,以实现网络应用.用户通过VC编程实现的网络软件可以在网络中不同的计算机之间互传文件,图像等信息.基础知识: 如果用户要进行VC网络编程,则必须首先了解计算机网络通信的基本框架和工作原理.在两台或多台计算机之间进行网络通信时,其通信的双方还必须遵循相同的通信原则好数据格式. 1.OSI七层网络模型OSI网络模型是一个开放式系统互联的参考模型. 发送信息的计算机 接收信息的计算机 7.应用层 7.应用层 表示计算机网络

MFC_网络编程socket套接字

MFC socket编程 MFC socket编程 ---- 一. 客户端 ---- 1. 创建一个Dialog Based项目:CSockClient. ---- 2. 设计对话框 ---- 去掉Ok和Cancle两个按钮,增加ID_Connect(连接).ID_Send(发送).ID_Exit(关闭)按钮,增加ListBox控件IDC_LISTMSG和Edit控件IDC_EDITMSG,并按下表在ClassWizard中为CCSockClientDlg类添加变量. Control ID Ty

C#网络程序设计(1)网络编程常识与C#常用特性

    网络程序设计能够帮我们了解联网应用的底层通信原理!     (1)网络编程常识: 1)什么是网络编程 只有主要实现进程(线程)相互通信和基本的网络应用原理性(协议)功能的程序,才能算是真正的网络编程. 2)网络编程的层次 现实中的互联网是按照"TCP/IP分层协议栈"的体系结构构建的,因此程序员必须搞清楚自己要做的是哪个层次上的编程工作. TCP/IP协议体系的实现情况: 其中,网络接口层已经被大多数计算机生产厂家集成在了主板上,也就是经常所说的网卡(NIC).windows操

网络编程学习小结

几种网络编程方式: ISAPI.CGI.WinInet.Winsock 它们之间的差别: 1)  ISAPI主要是开发基于浏览器client与server端程序.效率比CGI方式高,并且也扩展了CGI没有的一些功能.(基于TCP/IP模型中的应用层) 2)  CGI主要是开发基于浏览器client与server端程序.(基于TCP/IP模型中的应用层) 3)  WinInet主要是开发client程序.(基于TCP/IP模型中的应用层) 4)  Winsock主要是基于socket来开发clie