方法二:CAsyncSocket类

WinSock类

在Visual C++的MFC类库中,提供了两个与WinSock相关的类,分别为CAsyncSocket类和CSocket类。这两个类对WinSock API进行了封装,使得开发Windows Socket应用程序变得简单了。本节将针对CAsyncSocket和CSocket介绍Windows Socket应用程序的开发。

CAsyncSocket类介绍

CAsyncSocket类对WinSock API进行了低级封装,它提供的许多方法直接对应于低层的API函数。在使用CAsyncSocket时,首先需要调用构造函数创建CAsyncSocket对象,然后调用Create方法创建套接字句柄,对于服务器端的套接字,需要调用Listen方法使其处于监听模式,对于客户端套接字,需要调用Connect方法连接服务器。下面介绍CAsyncSocket的主要方法和事件。

(1)Create方法
Create方法用于创建一个Windows 套接字。
语法:

 

BOOL Create( UINT nSocketPort = 0, int nSocketType = SOCK_STREAM, long lEvent = FD_READ | 
FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE,
LPCTSTR lpszSocketAddress = NULL );

 

Create方法参数说明如表18.9所示。
表18.9 Create方法参数说明
参 数 名 称             参 数 描 述
nSocketPort               标识套接字端口
nSocketType              标识套接字类型,默认为流式套接字
lEvent                         表示套接字能够接受的事件
lpszSocketAddress     表示套接字的网络地址

 

(2)GetLastError方法
GetLastError方法用于获得最后一次操作失败的状态信息。
语法:

 

static int GetLastError( );

 


(3)GetPeerName方法
GetPeerName方法用于获得套接字连接的IP地址。
语法:

 

BOOL GetPeerName( CString& rPeerAddress, UINT& rPeerPort );
BOOL GetPeerName( SOCKADDR* lpSockAddr, int* lpSockAddrLen );

 


GetPeerName方法参数说明如表18.10所示。
表18.10 GetPeerName方法参数说明
参数名称               参 数 描 述
rPeerAddress               用于接收函数返回的IP地址
rPeerPort                     用于记录端口号
lpSockAddr                 是一个sockaddr结构指针,用于记录套接字名称
lpSockAddrLen           用于确定lpSockAddr的大小

 

(4)Accept方法
Accept方法用于接受一个套接字的连接。
语法:

 

virtual BOOL Accept( CAsyncSocket& rConnectedSocket, SOCKADDR* lpSockAddr = NULL, int* 
lpSockAddrLen = NULL );

 

rConnectedSocket:当前连接的套接字引用。
lpSockAddr:一个SOCKADDR结构指针,用于记录套接字地址。
lpSockAddrLen:确定lpSockAddr的大小。

注意:此处应该注意WinSocket的Accept函数的区别:

SOCKET accept( SOCKET s, struct sockaddr FAR *addr, int FAR *addrlen );

我们可以发现这个函数的返回值类型是SOCKET类型,也就是连接成功后我们在后面用于双方进行数据通讯的套接字,而上面的Accept方法它的返回值类型为BOOL类型,那么我们如何保存连接过后所生成的套接字呢?参数rConnectedSocket的作用就在这里,它保存连接后的套接字返回,因此,我们在调用Accept函数前要先建立一个
CAsyncSocket结构体来保存这个套接字

 

(5)Bind方法
Bind方法将本机地址关联到套接字上。
语法:

 

BOOL Bind( UINT nSocketPort, LPCTSTR lpszSocketAddress = NULL );
BOOL Bind ( const SOCKADDR* lpSockAddr, int nSockAddrLen );

 

Bind方法参数说明如表18.11所示。
表18.11 Bind方法参数说明
参数名称                参 数 描 述
nSocketPort                   标识套接字端口
lpszSocketAddress         标识IP地址
lpSockAddr                   是一个SOCKADDR结构指针,该结构记录了套接字的地址信息
nSockAddrLen              确定lpSockAddr的大小

 

(6)Close方法
Close方法用于关闭套接字。
语法:

 

virtual void Close( );

 

说明:
Close方法释放套接字描述符,因此,在调用该方法后,再对其进行访问,会导致错误。当CAsyncSocket对象被释放时,会自动调用Close方法。

(7)Connect方法
Connect方法用于建立一个套接字连接。
语法:

 

BOOL Connect( LPCTSTR lpszHostAddress, UINT nHostPort );
BOOL Connect( const SOCKADDR* lpSockAddr, int nSockAddrLen );

 

Connect方法参数说明如表18.12所示。
表18.12 Connect方法参数说明
参数名称                 参 数 描 述
lpszHostAddress             是主机的IP地址或网址
nHostPort                       标识当前应用程序的端口
lpSockAddr                   是一个SOCKADDR结构指针,该结构标识套接字地址信息
nSockAddrLen               确定lpSockAddr的大小

 

(8)Listen方法
Listen方法用于监听套接字的连接请求。
语法:

 

BOOL Listen( int nConnectionBacklog = 5 );

 


nConnectionBacklog:表示等待连接的最大队列长度。

(9)Receive方法
Receive方法用于从一个套接字上接收数据。
语法:

 

virtual int Receive( void* lpBuf, int nBufLen, int nFlags = 0 );

 


lpBuf:是接收数据的缓冲区。
nBufLen:确定缓冲区的长度。
nFlags:确定函数的调用模式,可选值如下。
l  MSG_PEEK用来查看传来的数据,在序列前端的数据会被复制一份到返回缓冲区中,但是这个数据不会从序列中移走。
l  MSG_OOB用来处理Out-Of-Band数据。

(10)ReceiveFrom方法
ReceiveFrom方法用于接收面向无连接传递的数据(数据报)。
语法:

 

int ReceiveFrom( void* lpBuf, int nBufLen, CString& rSocketAddress, UINT& rSocketPort, 
int nFlags = 0 );
int ReceiveFrom( void* lpBuf, int nBufLen, SOCKADDR* lpSockAddr, int* lpSockAddrLen,
int nFlags = 0 );

 

ReceiveFrom方法参数说明如表18.13所示。
表18.13 ReceiveFrom方法参数说明
参数名称          参 数 描 述
lpBuf                       是接收数据的缓冲区
nBufLen                  是缓冲区的大小
rSocketAddress      用于接收数据报的目的地(IP地址)
rSocketPort            用于记录端口号
lpSockAddr            是一个SOCKADDR结构指针,用于记录套接字地址信息
lpSockAddrLen       确定lpSockAddr的大小
nFlags                      标识函数调用方式

 

(11)Send方法
Send方法用于发送数据到连接的套接字上。
语法:

 

virtual int Send( const void* lpBuf, int nBufLen, int nFlags = 0 );

 


lpBuf:标识要发送数据的缓冲区。
nBufLen:确定缓冲区的大小。
nFlags:标识函数调用方法。

(12)SendTo方法
SendTo方法既可以在面向连接的套接字上发送数据,也可以在面向无连接的套接字上发送数据。
语法:

 

int SendTo( const void* lpBuf, int nBufLen, UINT nHostPort, LPCTSTR lpszHostAddress = 
NULL, int nFlags = 0 );
int SendTo( const void* lpBuf, int nBufLen, const SOCKADDR* lpSockAddr, int nSockAddrLen,
int nFlags = 0 );

 

SendTo方法参数说明如表18.14所示。
表18.14 SendTo方法参数说明
参数名称                参 数 描 述
lpBuf                              标识要发送数据的缓冲区
nBufLen                         确定缓冲区大小
nHostPort                      确定主机端口号
lpszHostAddress            确定主机地址(可以是域名或IP地址)
lpSockAddr                  是一个SOCKADDR结构指针,用于确定主机套接字地址信息
nSockAddrLen              确定lpSockAddr的大小
nFlags                            标识函数调用方式

 

(13)ShutDown方法
ShutDown方法用于在套接字上断开数据的发送或接收。
语法:

 

BOOL ShutDown( int nHow = sends );

 

nHow:确定ShutDown函数的行为,0表示不允许接收,1表示不允许发送,2表示不允许接收和发送。

(14)OnAccept事件
OnAccept事件在套接字接受连接请求时触发。
语法:

 

virtual void OnAccept( int nErrorCode );

 

nErrorCode:标识错误代码。

(15)OnClose事件
OnClose事件在连接的套接字被关闭时触发。
语法:

 

virtual void OnClose( int nErrorCode );

 


nErrorCode:标识错误代码。

(16)OnConnect事件
OnConnect事件在套接字被连接后触发。也就是在连接套接字调用Connect函数以后马上触发OnConnect事件
语法:

 

virtual void OnConnect( int nErrorCode );

 

nErrorCode:标识错误代码。

(17)OnOutOfBandData事件
OnOutOfBandData事件在接收数据的套接字收到Out-Of-Band数据时触发。
语法:

 

virtual void OnOutOfBandData( int nErrorCode );

 


nErrorCode:标识错误代码。

(18)OnReceive事件
OnReceive事件在套接字有数据被接收时触发。
语法:

 

virtual void OnReceive( int nErrorCode );

 


nErrorCode:标识错误代码。

(19)OnSend事件
OnSend事件在套接字发送数据时触发。
语法:

 

virtual void OnSend( int nErrorCode );

 


nErrorCode:标识错误代码。

你会发现,连接建立的同时,OnSend就第一次被触发了,嗯,这很好,但你现在还不想Send,你让OnSend
返回,干点其他的事情,等待下一次OnSend试试看?实际上,你再也等不到OnSend被触发了。因为,除
了第一次以外,OnSend的任何一次触发,都源于你调用了Send。

OnSend事件被触发的时候,就是通知你在这个时候,可以Send数据了,但是是否需要Send数据,取决于你自己,这个事件仅仅是在这个时候通知一下你,你有这个权利作send数据的操作。
OK,理解这一点,就要搞清楚OnSend被触发的时候,实际上因为底层协议的缓冲区有了一定的空间,可以向里面送一些数据,而Send就是往这个缓冲区里送。但假设缓冲区目前有1K的空闲,你提交了3K的数据,那么会得到10035,直到又有了1K或者2K的空闲空间,OnSend又会被触发,通知你我有空地了,你把剩下的数据继续发送吧?

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值