当前位置:编程学习 > C/C++ >>

重载成员函数使CAsyncSocket类支持IPX/SPX协议

 

 

    CAsyncSocket类是VC++的MFC里一个对WinSock API封装得很低级的一个类。适合于既想利用WinSock API的灵活性,又想享受MFC里的消息事件机制带来的方便情况下使用,但是CAsyncSocket不支持IPX/SPX协议。笔者最近在开发一个基于IPX/SPX协议传送SPX包的程序时候,重载了CAsyncSocket类的Create,Bind,Connect,Socket,Accept这五个成员函数,成功地使CAsyncSocket类支持了IPX/SPX协议。下面谈谈具体实现。

 

我们先看看AsyncSocket::Create()这个函数的定义

 

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);

 

第一个参数是套接字的端口,第二个参数是套接字的类型,默认为流式套接字。第三个参数是针对套接字产生的事件,第四个参数是套接字的地址,默认为NULL。下面是这个函数的实现:

BOOL CAsyncSocket::Create(UINT nSocketPort, int nSocketType,

long lEvent, LPCTSTR lpszSocketAddress)

{

if (Socket(nSocketType, lEvent))

{

if (Bind(nSocketPort,lpszSocketAddress))

return TRUE;

int nResult = GetLastError();

Close();

WSASetLastError(nResult);

}

return FALSE;

}

请仔细看上面的代码,其实Create函数就调用了两个函数,一个是Socket,一个是Bind.从上面这段代码里,我们还看不出是CAsyncSocket类对TCP/IP和IPX/SPX协议的处理不同之处。

那么我们就接下来看看Socket函数

BOOL Socket(int nSocketType=SOCK_STREAM, long lEvent =

FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE,

int nProtocolType = 0, int nAddressFormat = PF_INET);

接下来是Socket函数的实现

BOOL CAsyncSocket::Socket(int nSocketType, long lEvent,

int nProtocolType, int nAddressFormat)

{

ASSERT(m_hSocket == INVALID_SOCKET);

 

m_hSocket = socket(nAddressFormat,nSocketType,nProtocolType);

if (m_hSocket != INVALID_SOCKET)

{

CAsyncSocket::AttachHandle(m_hSocket, this, FALSE);

return AsyncSelect(lEvent);

}

return FALSE;

}

看清楚了,里面有一句

m_hSocket=socket(nAddressFormat,nSocketType,nProtocolType);

我想熟悉WinSock API编程的朋友一定会知道,其实这就是WinSock API里创建一个新的套接字。第一个参数nAddressFormat就是套接字使用的协议族,在winsock2.h里我们可以找到

#define PF_INET AF_INET

#define PF_IPX AF_IPX

这两个定义,PF_INET就是指我们新创建的套接字使用TCP/IP协议,PF_IPX就是使用IPX/SPX协议。

而第二个参数nSocketType默认的就是流式套接字,第三个参数nProtocolType是指定使用的协议类型。

在winsock2.h里有这样的定义

#define IPPROTO_IP 0

默认的参数0就是IP包。

在使用默认参数调用Create函数情况下,即

CAsyncSocket::Create();

到了CAsyncSocket::Socket函数

m_hSocket=socket(nAddressFormat,nSocketType,nProtocolType);

这一句这里就变成了

m_hSocket=socket(AF_INET,SOCK_STREAM,IPROTO_IP);

我想现在大家都已经很清楚了CAsyncSocket类之所以不支持IPX/SPX协议问题就在这一句上面,因为他默认的创建一个基于TCP/IP的流式或者数据包套接字。我们要让CAsyncSocket类支持IPX/SPX,首先就要修改这里。

 

而在WinSock API里,创建一个基于IPX/SPX协议传送SPX包的流式套接字应该是这样

SOCKET sdServer;

SOCKADDR_IPX IPXAddr;

int addrlen=sizeof(SOCKADDR_IPX);

 

sdServer=socket(AF_IPX,SOCK_STREAM,NSPROTO_SPX);

ZeroMemory(&IPXAddr,sizeof(SOCKADDR_IPX));

IPXAddr.safamily=AF_IPX;

IPXAddr.sa_socket=hotns(9000);

bind(sdServer,(PSOCKADDR)&IPXAddr,sizeof(SOCKADDR_IPX);

IPX应用程序通过bind把本地地址与套接字绑定在一起,绑定端口是9000。我们不需要在SOCKADDR_IPX里指定网络号和节点地址,bind函数会自动利用系统上第一个可用IPX网络接口来填充这些SOCKADDR_IPX结构里的相应字段。

 

所以我们在自己的类里重载的Socket函数应该是这样

BOOL Socket(int flg,int nSocketType=SOCK_STREAM, long lEvent =

FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE,

int nProtocolType = NSPROTO_SPX, int n

补充:软件开发 , C语言 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,