一、CAsyncSocket类

CAsyncSocket属于异步非阻塞类。

CAsyncSocket类采用了windows socket中的WSAAsyncSelect模型。CAsyncSocket 类是在很低的层次上对windows socket API进行了封装,它的成员函数和winsock API的函数调用直接对应,一个CAsyncSocket对象代表了一个windows套接字,它是网络通信的端点。该类将根据不同的windows套接字消息调用CAsyncSocket类的回调函数。

OnAccept

通知侦听套接字,它可以通过调用Accept,接受挂起连接请求

OnClose

通知套接字,关闭对它的套接字连接

OnConnect

通知连接套接字,连接尝试已经完成,无论成功或失败

OnOutOfBandData

通知接收套接字,在套接字上有带外数据读入,通常是忙消息

OnReceive

通知侦听套接字,通过调用Receive恢复数据

OnSend

通知套接字,通过调用Send,它可以发送数据

 

网络应用程序一般采用客户端/服务器模式,他们使用的CAsyncSocket编程有所不同,下面以表格的形式方式看一下服务器和客户端之间的不同

序号 服务端 客户端
1

构造一个套接字

CAsyncSocket sockServer

构造一个套接字

CAsyncSocket sockClient

2

创建SOCKET句柄,绑定到指定的端口

sockServer.Create(nPort);

创建SOCKET句柄,使用默认参数

sockClient.Create();

3

启动监听,时刻准备接收连接请求

sockServer.Listen();

 
4  

请求链接服务器

sockClient.Connect(strAddress,nPort)

5

构造一个新的空套接字

CAsyncSocket sockRecv;

接收连接

sockServer.Accept(sockRecv);

 
6

接收数据

sockRecv.Receive(pBuffer,nLen);

发送连接

sockClient.Send(pBuffer,nLen);

7

发送数据

sockRecv.Send(pBuffer,nLen);

接收数据

sockClient.Receive(pBuffer,nLen);

8

关闭套接字对象

sockRecv.Close();

关闭套接字对象

sockClient.Close();

ps:客户端与服务端都要首先构造一个CAsyncSocket对象,然后使用该对象的Create成员函数来创建底层的SOCKET句柄。服务器端要绑定到特定的端口

对于服务器端的套接字对象,应使用CAsyncSocket::Listen函数进行监听状态,一旦收到来自客户端的链接请求,就调用CAsyncSocket::Accept来接收。对于客户端的套接字对象,应当使用CAsyncSocket::Connect来连接到一个服务器端的套接字对象。建立链接之后,双方就可以按照应用层协议交换数据了。

这里需要注意,Accept是将一个新的空CAsyncSocket对象作为它的参数,在调用Accept之前必须构造这个对象。与客户端套接字的连接是通过它建立的,如果这个套接字对象退出,连接也就关闭。对于这个新的套接字对象,不需要调用Create来创建它的底层套接字

调用CAsyncSocket对象的其他成员函数,如Send和Receive执行与其他套接字对象的通信,这些成员函数与Windows Sockets API函数在形式和用法上基本是一致的。

关闭并销毁CAsyncSocket对象。如果在堆栈上创建了套接字对象,当包含此对象的函数退出时,会调用该类的析构函数,销毁该对象。在销毁该对象之前,析构函数会调用该对象的Close成员函数。如果在堆上使用new创建了套接字对象,可先调用Close成员函数关闭它,在使用delete来删除释放该对象。

CAsyncSocket编程注意问题:

a) 阻塞处理。CAsyncSocket对象专用于异步操作,不支持阻塞工作模式,如果应用程序需要支持阻塞操作,必须自己解决。

b) 字节顺序的转换。在不同的结构类型的计算机之间进行数据传输时,可能会有计算机之间字节存储顺序不一致的情况,需要自己对不用的字节顺序进行转换。

c) 字符串转换。同样不同结构类型的计算机的字符串顺序也可能不同,需要自行转换。

d)在使用CAsyncSocket之前,必须调用AfxSocketInit初始化WinSock环境,而AfxSocketInit会创建一个隐藏的CSocketWnd对象,由于这个对象由Cwnd派生,因此它能够接收Windows消息。一方面它会接受各个CAsyncSocket的状态报告,另一方面它能捕捉系统发出的各种SOCKET事件,其通信流程如下。

二、CSocket类

CSocket是MFC在CAsyncSocket基础上派生的一个同步阻塞Socket的封装类。

CSocket类是从CAsyncsocket派生而来的,它继承了CAsyncsocket对WindowsSockets API的封装。与CAsyncsocket对象相比,CSocket对象代表了WindowsSockets API的更高一级的抽象化。

a)在使用MFC编写socket程序时,必须要包含<afxsock.h>都文件。

b) AfxSocketInit() 这个函数,在使用CSocket前一定要先调用该函数,否则使用CSocket会出错;并且该函数还有一个重要的使用方式,就是在某个线程下使用 CSocket 前一定要调用,就算主线程调用了该函数,在子线程下使用 CSocket 也要先调用该函数,要不会出错。

c) 还要注意的是, Create 方法已经包含了 Bind 方法,如果是以 Create 方法初始化的前提下不能再调用 Bind ,要不一定出错。

三、代码实现

设计两个对话框应用程序,通过TCP/IP进行通信,使用MFC的CSocket类实现服务器端和客户端之间的相互通信。

3.1服务器端

服务器端的socket通信需要用到两个socket:

  1. 用来监听连接的socket
  2. 用来和客户端通信的socket,此socket中保存了客户端信息

因此服务器端需要添加两个继承自CSocket的类,分别起名为CServerSocket、CConnectSocket。

3.1.1 CServerSocket

  此socket主要用来监听客户端请求,当有请求到来时,MFC框架将调用OnAccept函数,所以我们需要重写CSocket类的OnAccept函数。

 /////////////////////////////////////////////////////////
# ServerSocket.h 文件
/////////////////////////////////////////////////////////
class CServerSocket : public CSocket
{
public:
CServerSocket();
virtual ~CServerSocket(); void OnAccept(int nErrorCode);
//开启socket服务
void StartServer(UINT nPort);
//发送消息函数
void MessageSend(const char* pMesg); private:
//保存的是客户端的socket信息
CConnectSocket m_clientSock;
};

  在OnAccept函数中调用Accept函数,接受客户端请求,另外将客户信息保存到m_clientSock中,使用此套接字对象与客户端进行通信,发送信息可以直接调用API函数Send。

  在StartServer函数中做了两件事儿,创建套接字,监听套接字。需要主要的是Create函数内部已经对套接字进行了绑定,所以不需要再次绑定。

 /////////////////////////////////////////////////////////
# ServerSocket.cpp 文件
/////////////////////////////////////////////////////////
void CServerSocket::OnAccept(int nErrorCode)
{
Accept(m_clientSock);
CSocket::OnAccept(nErrorCode);
} void CServerSocket::StartServer(UINT nPort)
{
if (!Create(nPort))
{
AfxMessageBox(_T("Socket 创建失败!"));
return;
}
if (!Listen())
{
AfxMessageBox(_T("Socket 监听失败!"));
return;
}
} void CServerSocket::MessageSend(const char* pMesg)
{
m_clientSock.Send(pMesg, strlen(pMesg) + );
}

3.1.2CConnectSocket类

  此类中保存了客户端信息,所以用来与客户端进行通信,重写了OnSend和OnReceive函数,这两个函数由MFC框架调用。

 /////////////////////////////////////////////////////////
# ConnectSocket.h 文件
/////////////////////////////////////////////////////////
class CConnectSocket : public CSocket
{
public:
CConnectSocket();
virtual ~CConnectSocket(); //函数重写
void OnSend(int nErrorCode);
void OnReceive(int nErrorCode);
};

当客户端与客户端连接成功之后服务器端框架会调用OnSend函数给客户端发送通知。另外,当服务器端接收到客户端发来的消息之后,MFC框架会调用OnReceive函数,我们可以在此函数中对接收到的消息进行处理。

 /////////////////////////////////////////////////////////
# ConnectSocket.cpp 文件
/////////////////////////////////////////////////////////
void CConnectSocket::OnSend(int nErrorCode)
{
char* pSend = "你好, 我是服务器,我们已经成功建立了连接!";
Send(pSend, strlen(pSend) + );
CSocket::OnSend(nErrorCode);
} void CConnectSocket::OnReceive(int nErrorCode)
{
char bufRecv[];
int nCount = Receive(bufRecv, );
bufRecv[nCount] = ;
CUnicodeAndChar uc;
CString str = uc.MultiToWide(string(bufRecv));
AfxMessageBox(str);
CSocket::OnReceive(nErrorCode);
}

MFC- socket 编程的更多相关文章

  1. mfc socket编程

    socket编程用法---- 随着计算机网络化的深入,计算机网络编程在程序设计的过程中变得日益重要.由于C++语言对底层操作的优越性,许多文章都曾经介绍过用VC++进行Socket编程的方法.但由于都 ...

  2. 基于MFC的socket编程

    网络编程 1.windows 套接字编程(开放的网络编程接口)添加头文件#include<windows.h> 2.套接字及其分类 socket分为两种:(1)数据报socket:无连接套 ...

  3. 基于MFC的socket编程(异步非阻塞通信)

       对于许多初学者来说,网络通信程序的开发,普遍的一个现象就是觉得难以入手.许多概念,诸如:同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)等,初学者往往迷惑不清, ...

  4. 揭开Socket编程的面纱

    对TCP/IP.UDP.Socket编程这些词你不会很陌生吧?随着网络技术的发展,这些词充斥着我们的耳朵.那么我想问: 1. 什么是TCP/IP.UDP? 2. Socket在哪里呢? 3. Sock ...

  5. Socket编程学习之道:揭开Socket编程的面纱

    对TCP/IP.UDP.Socket编程这些词你不会非常陌生吧?随着网络技术的发展.这些词充斥着我们的耳朵. 那么我想问: 1.         什么是TCP/IP.UDP? 2.         S ...

  6. 【转】揭开Socket编程的面纱

    对TCP/IP.UDP.Socket编程这些词你不会很陌生吧?随着网络技术的发展,这些词充斥着我们的耳朵.那么我想问: 1.         什么是TCP/IP.UDP?2.         Sock ...

  7. 转:MFC网络编程学习

    要学习好网路编程,主要看以下几个方面: 1.掌握概念,诸如:同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)等. 2.在实际Windows网络通信软件开发中,异步非阻 ...

  8. Socket编程(摘抄)

    http://www.blogjava.net 例子代码就在我的博客中,包括六个UDP和TCP发送接受的cpp文件,一个基于MFC的局域网聊天小工具工程,和此小工具的所有运行时库.资源和执行程序.代码 ...

  9. Socket编程指南及示例程序

    例子代码就在我的博客中,包括六个UDP和TCP发送接受的cpp文件,一个基于MFC的局域网聊天小工具工程,和此小工具的所有运行时库.资源和执行程序.代码的压缩包位置是http://www.blogja ...

  10. 《转》MFC网络编程学习

    原地址:http://www.cnblogs.com/renyuan/archive/2013/06/04/3117006.html要学习好网路编程,主要看以下几个方面: 1.掌握概念,诸如:同步(S ...

随机推荐

  1. 洛谷 P1140 相似基因 ( 线性DP || 类LCS )

    题意 : 题目链接 分析 :  可以观察到给出的配对代价表中对角线部分是正数 其余的都是负数,也就是说让相同字母的匹配的越多越好 即找出 LCS 但是这里 DP 的过程需要记录一下代价 有关 LCS ...

  2. spring 接口校验参数(自定义注解)

    1. 注解类 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.l ...

  3. [BZOJ4010]:[HNOI2015]菜肴制作(拓扑排序)

    题目传送门 题目描述 知名美食家小A被邀请至ATM大酒店,为其品评菜肴. ATM酒店为小A准备了N道菜肴,酒店按照为菜肴预估的质量从高到低给予1到N的顺序编号,预估质量最高的菜肴编号为1.由于菜肴之间 ...

  4. sh脚本获取当前目录

    #!/bin/bashcurDir=$(pwd)echo "cur dir is:$curDir"

  5. java 栈和栈帧

    文章转载自:http://www.tuicool.com/articles/URZrMnb jvm为每个新创建的线程都分配一个堆栈.堆栈以帧为单位保存线程的状态.jvm对堆栈只进行两种操作:以帧为单位 ...

  6. 无法加载程序集XXX.dll 此程序集可能是从 Web 上下载的

    错误    13    无法加载程序集 file:///D:\Documents\Downloads\kaxaml-master\kaxaml-master\packages\Prism.4.0.0. ...

  7. http-server 建立 HTTPS 服务

    1. 创建证书 进入要建立 HTTPS 服务的目录 openssl genrsa -out key.pem 1024 openssl req -new -key key.pem -out csr.pe ...

  8. 细数EDM营销中存在的两大盲点

    国庆节了,祝大家国庆快乐,转眼博客至今已有三年了.下面博主为大家介绍EDM营销中存在的两大盲点,供大家参考. 一是忽略用户友好.用户友好策略是Email营销成功的关键要素,具体包括内容友好策略.方式友 ...

  9. jenkins不展示set Build Description Setter插件

    问题描述: 1.jenkins 已下载 set build descripteion ,并且配置过,可以在构建历史中展示就用二维码 2.问题:构建历史中不展示二维码了,如图: 总是排查: 1.首先想到 ...

  10. msyql 计划任务 备份数据库

    用计划任务备份数据库 把exam库备份到家(home)目录下 [root@izuf66j5nlb2arg99viiuwz /]# mysqldump -u root -p exam > ~/ex ...