程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 重載成員函數使CAsyncSocket類支持IPX/SPX協議

重載成員函數使CAsyncSocket類支持IPX/SPX協議

編輯:關於C語言

 

 

    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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved