首 页IT知识库翔宇问吧收藏本站
当前位置:翔宇亭IT乐园IT知识库编程技术C/C++

Visual C++之WinSock编程介绍

减小字体 增大字体 作者:不详  来源:中华网  发布时间:2011-03-16 16:22:21

考虑到一个应用程序通常用与"时间"服务对应的端口来和服务器连接,而服务器提供某种机制来通知用户使用另一端口。因此 getservbyname()函数返回的端口号已经是网络顺序了,可以直接用来组成一个地址,而不需要进行转换。然而如果用户输入一个数,而且指定使用这一端口号,应用程序则必须在使用它建立地址以前,把它从主机顺序转换成网络顺序(使用htons()函数)。相应地,如果应用程序希望显示包含于某一地址中的端口号(例如从getpeername()函数中返回的),这一端口号就必须在被显示前从网络顺序转换到主机顺序(使用ntohs()函数)。

由于 Intel处理器和Internet的字节顺序是不同的,上述的转换是无法避免的,应用程序的编写者应该使用作为Windows Sockets API一部分的标准的转换函数,而不要使用自己的转换函数代码。因为将来的Windows Sockets实现有可能在主机字节顺序与网络字节顺序相同的机器上运行。因此只有使用标准的转换函数的应用程序是可移植的。

在MFC中 MS为套接口提供了相应的类CAsyncSocket和CSocket,CAsyncSocket提供基于异步通信的套接口封装功能,CSocket则是由CAsyncSocket派生,提供更加高层次的功能,例如可以将套接口上发送和接收的数据和一个文件对象(CSocketFile)关联起来,通过读写文件来达到发送和接收数据的目的,此外CSocket提供的通信为同步通信,数据未接收到或是未发送完之前调用不会返回。此外通过MFC类开发者可以不考虑网络字节顺序和忽略掉更多的通信细节。

在一次网络通信/连接中有以下几个参数需要被设置:本地IP地址 - 本地端口号 - 对方端口号 - 对方IP地址。左边两部分称为一个半关联,当与右边两部分建立连接后就称为一个全关联。在这个全关联的套接口上可以双向的交换数据。如果是使用无连接的通信则只需要建立一个半关联,在发送和接收时指明另一半的参数就可以了,所以可以说无连接的通信是将数据发送到另一台主机的指定端口。此外不论是有连接还是无连接的通信都不需要双方的端口号相同。

在创建CAsyncSocket对象时通过调用
BOOL CAsyncSocket::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 )通过指明lEvent所包含的标记来确定需要异步处理的事件,对于指明的相关事件的相关函数调用都不需要等待完成后才返回,函数会马上返回然后在完成任务后发送事件通知,并利用重载以下成员函数来处理各种网络事件:

 标记  事件  需要重载的函数
 FD_READ  有数据到达时发生  void OnReceive( int nErrorCode );
 FD_WRITE  有数据发送时产生  void OnSend( int nErrorCode );
 FD_OOB  收到外带数据时发生  void OnOutOfBandData( int nErrorCode );
 FD_ACCEPT  作为服务端等待连接成功时发生  void OnAccept( int nErrorCode );
 FD_CONNECT  作为客户端连接成功时发生  void OnConnect( int nErrorCode );
 FD_CLOSE   套接口关闭时发生  void OnClose( int nErrorCode );

我们看到重载的函数中都有一个参数nErrorCode,为零则表示正常完成,非零则表示错误。通过int CAsyncSocket::GetLastError()可以得到错误值。

下面我们看看套接口类所提供的一些功能,通过这些功能我们可以方便的建立网络连接和发送数据。

 * BOOL CAsyncSocket::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 );用于创建一个本地套接口,其中nSocketPort为使用的端口号,为零则表示由系统自动选择,通常在客户端都使用这个选择。 nSocketType为使用的协议族,SOCK_STREAM表明使用有连接的服务,SOCK_DGRAM表明使用无连接的数据报服务。 lpszSocketAddress为本地的IP地址,可以使用点分法表示。

* BOOL CAsyncSocket::Bind( UINT nSocketPort, LPCTSTR lpszSocketAddress = NULL )作为等待连接方时产生一个网络半关联,或者是使用UDP协议时产生一个网络半关联。

* BOOL CAsyncSocket::Listen( int nConnectionBacklog = 5 )作为等待连接方时指明同时可以接受的连接数,请注意不是总共可以接受的连接数。

* BOOL CAsyncSocket::Accept( CAsyncSocket& rConnectedSocket, SOCKADDR* lpSockAddr = NULL, int* lpSockAddrLen = NULL )作为等待连接方将等待连接建立,当连接建立后一个新的套接口将被创建,该套接口将会被用于通信。

* BOOL CAsyncSocket::Connect( LPCTSTR lpszHostAddress, UINT nHostPort );作为连接方发起与等待连接方的连接,需要指明对方的IP地址和端口号。

* void CAsyncSocket::Close( );关闭套接口。

* int CAsyncSocket::Send( const void* lpBuf, int nBufLen, int nFlags = 0 )  int CAsyncSocket::Receive( void* lpBuf, int nBufLen, int nFlags = 0 );在建立连接后发送和接收数据,nFlags为标记位,双方需要指明相同的标记。

*int CAsyncSocket::SendTo( const void* lpBuf, int nBufLen, UINT nHostPort, LPCTSTR lpszHostAddress = NULL, int nFlags = 0 )
        int CAsyncSocket::ReceiveFrom( void* lpBuf, int nBufLen, CString&rSocketAddress, UINT& rSocketPort, int nFlags = 0 );对于无连接通信发送和接收数据,需要指明对方的IP地址和端口号,nFlags为标记位,双方需要指明相同的标记。

我们可以看到大多数的函数都返回一个布尔值表明是否成功。如果发生错误可以通过int CAsyncSocket::GetLastError()得到错误值。

由于CSocket由CAsyncSocket派生所以拥有CAsyncSocket的所有功能,此外你可以通过BOOL CSocket::Create( UINT nSocketPort = 0, int nSocketType = SOCK_STREAM, LPCTSTR lpszSocketAddress = NULL )来创建套接口,这样创建的套接口没有办法异步处理事件,所有的调用都必需完成后才会返回。

在上面的介绍中我们看到MFC提供的套接口类屏蔽了大多数的细节,我们只需要做很少的工作就可以开发出利用网络进行通信的软件。

上一页  [1] [2] 

知识评论评论内容只代表网友观点,与本站立场无关!

   评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论

用户名: 查看更多评论

分 值:100分 85分 70分 55分 40分 25分 10分 1分

内 容:

            请注意用语文明且合法,不要发布带有攻击性、侮辱性的言论,谢谢合作!

         通知管理员 验证码:

关于本站 | 网站帮助 | 广告合作 | 网站声明 | 友情连接 | 网站地图 | 用户守则 | 联系我们 |
本站大多数内容来自互联网或网站会员发布,如有侵权,请来信告之,谢谢!
Copyright © 2007-2017 biye5u.com. All Rights Reserved.
网站备案号:黑ICP备13005378号-3