The heavy-duty member function allows the CasyncSocket class to support IPXSPX protocol

zhaozj2021-02-08  214

The author of this question is originally reproduced, please indicate the source. Overload member functions to make CasyncSocket classes support IPX / SPX protocol -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------------- CasyncSocket class is a VC MFC A very low class for the Winsock API package. Suitable for both Winsock API's flexibility, and want to use the message event mechanism in the MFC, CasyncSocket does not support IPX / SPX protocols. The author recently developed a program of the CasyncSocket class for the CASYNCSocket class, which has been developed, Bind, Connect, Socket, Accept, successfully loaded the CasyncSocket class to support the CasyncSocket class with the IPX / SPX protocol. Let's talk about specific implementation. Let's take a look at AsyncSocket :: Create () function is defined 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); first The parameter is the port of the socket, the second parameter is the type of socket, the default is the streaming socket. The third parameter is an event generated for the socket, the fourth parameter is the address of the socket, and the default is NULL. The following is implementation of this function: 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;} Please take a closer look, in fact, the create function calls two functions, one is socket, one is bind. From above this code We also see that the CasyncSocket class is different from the processing of TCP / IP and IPX / SPX protocol.

Then we look at the next Socket function 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); followed by the realization Socket functions 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 false;} There is a M_HSOCKET = Socket (NaddressFormat, nsockettype, nprotocoltype); I want to be familiar with Winsock API programming, actually This is the Winsock API creates a new socket. The first parameter NaddressFormat is the protocol used by the socket. In Winsock2.h, we can find the two definitions of #DEFINE PF_INET AF_IPX # define pf_ipx AF_IPX, and PF_INET refers to our newly created socket using TCP / IP protocol. PF_IPX is using the IPX / SPX protocol. The second parameter NSocketType default is the streaming socket, the third parameter nProtocolType is the type of protocol that specifies the use. There is such defined parameter 0 by default #define ipproto_ip 0 in Winsock2.h is an IP package. In the default case Create function call parameters, i.e. CAsyncSocket :: Create (); to the CAsyncSocket :: Socket function m_hSocket = socket (nAddressFormat, nSocketType, nProtocolType); here, it becomes a m_hSocket = socket (AF_INET, SOCK_STREAM, IProto_IP); I think everyone is now very clear that the CasyncSocket class does not support IPX / SPX protocol issues on this sentence because he defaults to create a TCP / IP stream or packet. We want the CasyncSocket class to support IPX / SPX, first modify here. In the WinSock API, the created based IPX / SPX protocol SPX transport packet stream socket should be such 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 the application via a local socket address The word is bound, the binding port is 9000.

We don't need to specify the network number and node address in SockAddr_ipx, and the Bind function automatically uses the first IPX network interface on the system to populate the corresponding fields in these SockAddr_ipx structures. So we own the Socket class overloaded function should be so 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 nAddressFormat = PF_IPX ); BOOL CMySocket :: Socket (int flg, 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 (});} Return False;} More parameter flg is more than one parameter FLG, which is used to distinguish functions after heavy load And the original function. The other parameters have not changed, please pay attention to the default parameters in the function declaration. nProtocolType The default value of the parameter changed NSPROTO_SPX, nAddressFormat default value of this parameter has changed PF_IPX. Next we look Bind function CAsyncSocket class, CAsyncSocket class defines two Bind function BOOL Bind (UINT nSocketPort, LPCTSTR lpszSocketAddress = NULL); BOOL BIND (Const SockAddr * LPSockAddr, Int NsockAddrlen); only the first BIND function is only available in the original code of the MFC.

BOOL CAsyncSocket :: Bind (UINT nSocketPort, LPCTSTR lpszSocketAddress) {USES_CONVERSION; SOCKADDR_IN sockAddr; memset (& sockAddr, 0, sizeof (sockAddr)); LPSTR lpszAscii = T2A ((LPTSTR) lpszSocketAddress); sockAddr.sin_family = AF_INET; if (lpszAscii == NULL) sockAddr.sin_addr.s_addr = htonl (INADDR_ANY); else {DWORD lResult = inet_addr (lpszAscii); if (lResult == INADDR_NONE) {WSASetLastError (WSAEINVAL); return FALSE;} sockAddr.sin_addr.s_addr = lResult; } sockaddr.sin_port = htons ((u_short) nsocketport); returnaddr *) & sockaddr, sizeof (sockaddr));} I don't know if you have noticed that there is no, in the last sentence of this function calls a bind function, This function is obviously Bool Bind (const socddr * lpsockaddr, int nsockaddrlen); the specific original code of this function we don't know, but his two parameters, the first parameter passed into the SockAddr structure, the second parameter passed in The length of this structure. The Bind function original of Winsock API is int Bind (Socket S, INT Namelen); we can imagine, bind (socketdr *) & sociDDr, sizeof (socketdr)); this function is definitely called Winsock The bind function in the API. How do we do it, we don't have to manage, we will take advantage of Bind (SockAddr *) & SockAddr, Sizeof (SockAddr)); the parameters passing here are OK.

So we will just reload BOOL Bind (UINT nSocketPort, LPCTSTR lpszSocketAddress = NULL); function, the following is the first function BOOL Bind Bind overloaded (int flg, UINT nSocketPort, LPCTSTR lpszSocketAddress = NULL); BOOL CMySocket: : Bind (int flg, UINT nSocketPort, LPCTSTR lpszSocketAddress) {USES_CONVERSION; SOCKADDR_IPX sockAddr; memset (& sockAddr, 0, sizeof (sockAddr)); sockAddr.sa_family = AF_IPX; sockAddr.sa_socket = htons ((u_short) nSocketPort); return CAsyncSocket :: Bind ((psockaddr) & sockaddr, sizeof (sockaddr));} Now we are in CasyncSocket :: Bind ((PSockAddr) & SockAddr, SIZEOF (SockAddr)); here delivery is a PSockAddr structure that supports IPX, which is defined wsipx.h header file typedef struct sockaddr_ipx {short sa_family; // protocol suite char sa_netnum [4]; // network address char sa_nodenum [6]; // node address unsigned short sa_socket; // port} sOCKADDR_IPX, * PSOCKADDR_IPX, Far * lpsockAddr_ipx; now these functions are overloaded, let's look back at the create function, and the re-load Create function should be as follows Bool Create (int FLG, UINT NSOCKETPORT = 0, int NSocketType = Sock_Stream, long levent = fd_read | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE, LPCTSTR LPSZSOCKETDRESS = NULL); BOOL CMYSOCKET :: Create (int FLG, UINT nSocketPort, int nSocketType, long lEvent, LPCTSTR lpszSocketAddress) {if (Socket (flg, nSocketType, lEvent)) {if (Bind (flg, nSocketPort, lpszSocketAddress)) return TRUE; int nResult = GetLastError (); Close (); WSASetLastError (} Return False;} After we created the socket of the IPX / SPX protocol in the MFC program, we can just like this. MySocket TestSocket; TestSocket.create (0); This creates a client cover that supports the IPX / SPX protocol, if you create a server-side socket, just change to the following code mysocket testsocket; testsocket.create (0, 10000); this creates a listening port of 10000, supporting a server-side stream socket that supports IPX / SPX to transfer SPX packages. We have to overload the CONNECT and Accept function processes. First, let's take a look at their MFC code, there are two Connect functions. For the second Connect function, we don't need tubes, as long as the first one is overloaded.

BOOL Connect (LPCTSTR lpszHostAddress, UINT nHostPort); BOOL Connect (const SOCKADDR * lpSockAddr, int nSockAddrLen); BOOL CAsyncSocket :: Connect (LPCTSTR lpszHostAddress, UINT nHostPort) {USES_CONVERSION; ASSERT (lpszHostAddress = NULL!); SOCKADDR_IN sockAddr; memset ( & sockAddr, 0, sizeof (sockAddr)); LPSTR lpszAscii = T2A ((LPTSTR) lpszHostAddress); sockAddr.sin_family = AF_INET; sockAddr.sin_addr.s_addr = inet_addr (lpszAscii); if (sockAddr.sin_addr.s_addr == INADDR_NONE) { LPHOSTENT lphost; lphost = gethostbyname (lpszAscii); if (lphost = NULL!) sockAddr.sin_addr.s_addr = ((LPIN_ADDR) lphost-> h_addr) -> s_addr; else {WSASetLastError (WSAEINVAL); return FALSE;}} sockAddr. SIN_PORT = HTONS ((u_short) NHOSTPORT; RETURN Connect ((SockAddr *) & SockAddr, Sizeof (SockAddr));} We have to consider a problem, which is the method of address and TCP / IP under the IPX / SPX protocol. Different, the address of the IPX / SPX is represented by 4-bit network addresses and 6-bit node addresses, such as 00000000.0000000000 The code after the CONNECT function overloaded is as follows: BOOL Connect (int FLG, LPCTSTSTSZZHOSTADDRESS, LPCTSTSTSZHOSTADDRESSS, UINT NHOSTPORT); BOOL CMYSOCKET :: Connect (int FLG, LPCTSTSTR LPSZHOSTADDRE ss, LPCTSTR lpszHostAddressse, UINT nHostPort) {USES_CONVERSION; ASSERT (lpszHostAddress = NULL);! ASSERT (lpszHostAddressse = NULL);! SOCKADDR_IPX sockAddr; memset (& sockAddr, 0, sizeof (sockAddr)); sockAddr.sa_family = AF_IPX; char * num = (LPSTR) (LPCSTR) lpszHostAddress; char * node = (LPSTR) (LPCSTR) lpszHostAddressse; AtoH (sockAddr.sa_netnum, num, 4); AtoH (sockAddr.sa_nodenum, node, 6); sockAddr.sa_socket = htons ( (U_SHORT) NHOSTPORT; RETURN CASYNCSOCKET :: Connect (PSockAddr) & SockAddr, Sizeof (SockAddr));} The ATOH function here is to convert the IPX / SPX address.

Uchar BTOH (CHAR CH) {IF ((CH> = ɔ ') && (CH <= ə')) {return (ch - ɔ ');} if ((ch> =' a ') && (ch <= 'F')) {RETURN (CH - 'A' 0xA);} IF ((CH> = 'a') && (CH <= 'f')) {RETURN (CH - 'A' 0xA); }} void atoh (char * szdest, char * szsource, int icount) {while (iCount -) {* szdest = (BTOH (* szsource ) << 4) btoh (* szsource );} return;} overload Accept function, MFC in the Accept function code is as follows: virtual BOOL Accept (CAsyncSocket & rConnectedSocket, SOCKADDR * lpSockAddr = NULL, int * lpSockAddrLen = NULL); BOOL CAsyncSocket :: Accept (CAsyncSocket & rConnectedSocket, SOCKADDR * lpSockAddr, int * lpSockAddrLen) {ASSERT (rConnectedSocket.m_hSocket == INVALID_SOCKET); ASSERT (CAsyncSocket :: FromHandle (INVALID_SOCKET) == NULL); CAsyncSocket :: AttachHandle (INVALID_SOCKET, & rConnectedSocket); SOCKET hTemp = accept (m_hSocket, lpSockAddr, lpSockAddrLen); if (hTemp == INVALID_SOCKET) {DWORD dwProblem = GetLastError (); CAsyncSocket :: DetachHandle (rConnectedSocket.m_hSocket, FALSE); rConnectedSocket.m_hSocket = INVALID_SOCKET; SetLastError (dwProblem);} else if (CAsyncSoc ! Ket :: FromHandle (INVALID_SOCKET) = NULL) {rConnectedSocket.m_hSocket = hTemp; CAsyncSocket :: DetachHandle (INVALID_SOCKET, FALSE); CAsyncSocket :: AttachHandle (hTemp, & rConnectedSocket);} return (hTemp = INVALID_SOCKET);!} Watched After the source code of the MFC, we find that as long as the type of the second parameter is changed.

转载请注明原文地址:https://www.9cbs.com/read-2621.html

New Post(0)