⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 socketutils.cpp

📁 跨操作系统的微型中间件
💻 CPP
字号:
/*    File:       SocketUtils.cpp    Contains:   Implements utility functions defined in SocketUtils.h                            */#include "SocketUtils.h"
#include <string.h>#ifndef __Win32__#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <sys/ioctl.h>#include <unistd.h>#include <sys/utsname.h>#endifusing namespace std;#ifdef SIOCGIFNUM#define USE_SIOCGIFNUM 1#endifUInt32                          SocketUtils::sNumIPAddrs = 0;SocketUtils::IPAddrInfo*        SocketUtils::sIPAddrInfoArray = NULL;//Version for all non-FreeBSD platforms.void SocketUtils::Initialize(Bool lookupDNSName){	return;	//Armer 需要比较长的时间,既然暂时没有用到,故屏蔽#if defined(__Win32__)     int tempSocket = ::socket(AF_INET, SOCK_DGRAM, 0);    if (tempSocket == -1)        return;#ifdef __Win32__    static const UInt32 kMaxAddrBufferSize = 20480;		//modify by puzy     char inBuffer[kMaxAddrBufferSize];    char outBuffer[kMaxAddrBufferSize];    UInt32 theReturnedSize = 0;        //    // Use the WSAIoctl function call to get a list of IP addresses    int theErr = ::WSAIoctl(    tempSocket, SIO_GET_INTERFACE_LIST,                                 inBuffer, kMaxAddrBufferSize,                                outBuffer, kMaxAddrBufferSize,                                &theReturnedSize,                                NULL,                                NULL);    Assert(theErr == 0);    if (theErr != 0)        return;        Assert((theReturnedSize % sizeof(INTERFACE_INFO)) == 0);        LPINTERFACE_INFO addrListP = (LPINTERFACE_INFO)&outBuffer[0];        sNumIPAddrs = theReturnedSize / sizeof(INTERFACE_INFO);#else	//get the number of network addresses#if defined(USE_SIOCGIFNUM)    if (::ioctl(tempSocket, SIOCGIFNUM, (char*)&sNumIPAddrs) == -1)    {        sNumIPAddrs = 64;    }#else	#error  //error warnning#endif    struct ifconf ifc;    ::memset(&ifc,0,sizeof(ifc));    ifc.ifc_len = sNumIPAddrs * sizeof(struct ifreq);    ifc.ifc_buf = (caddr_t)new struct ifreq[sNumIPAddrs];    Assert(ifc.ifc_buf != NULL);    ::memset(ifc.ifc_buf, '\0', ifc.ifc_len);    int theErr = ::ioctl(tempSocket, SIOCGIFCONF, (char*)&ifc);    Assert(theErr == 0);    if (theErr != 0)        return;    struct ifreq* ifr = (struct ifreq*)ifc.ifc_buf;#endif        //allocate the IPAddrInfo array. Unfortunately we can't allocate this    //array the proper way due to a GCC bug    UInt8* addrInfoMem = new UInt8[sizeof(IPAddrInfo) * sNumIPAddrs];    ::memset(addrInfoMem, 0, sizeof(IPAddrInfo) * sNumIPAddrs);    sIPAddrInfoArray = (IPAddrInfo*)addrInfoMem;    //for (UInt32 addrCount = 0; addrCount < sNumIPAddrs; addrCount++)    UInt32 currentIndex = 0;    for (UInt32 theIfCount = sNumIPAddrs, addrCount = 0;         addrCount < theIfCount; addrCount++)    {#ifdef __Win32__        // We *should* count the loopback interface as a valid interface.        //if (addrListP[addrCount].iiFlags & IFF_LOOPBACK)        //{            // Don't count loopback addrs        //  sNumIPAddrs--;        //  continue;        //}        //if (addrListP[addrCount].iiFlags & IFF_LOOPBACK)        //  if (lookupDNSName) // The playlist broadcaster doesn't care        //      Assert(addrCount > 0); // If the loopback interface is interface 0, we've got problems                    struct sockaddr_in* theAddr = (struct sockaddr_in*)&addrListP[addrCount].iiAddress;#elif defined(USE_SIOCGIFNUM)        if (ifr[addrCount].ifr_addr.sa_family != AF_INET)        {            sNumIPAddrs--;            continue;        }        struct ifreq ifrf;        ::memset(&ifrf,0,sizeof(ifrf));        ::strncpy(ifrf.ifr_name, ifr[addrCount].ifr_name, sizeof(ifrf.ifr_name));        theErr = ::ioctl(tempSocket, SIOCGIFFLAGS, (char *) &ifrf);        Assert(theErr != -1);        /* Skip things which aren't interesting */        if ((ifrf.ifr_flags & IFF_UP) == 0 ||            (ifrf.ifr_flags & (IFF_BROADCAST | IFF_POINTOPOINT)) == 0)        {            sNumIPAddrs--;            continue;        }        if (ifrf.ifr_flags & IFF_LOOPBACK)        {            Assert(addrCount > 0); // If the loopback interface is interface 0, we've got problems        }                struct sockaddr_in* theAddr = (struct sockaddr_in*)&ifr[addrCount].ifr_addr;        #if 0        puts(ifr[addrCount].ifr_name);    #endif#else#error#endif        char* theAddrStr = ::inet_ntoa(theAddr->sin_addr);        //store the IP addr        sIPAddrInfoArray[currentIndex].fIPAddr = ntohl(theAddr->sin_addr.s_addr);                //store the IP addr as a string        sIPAddrInfoArray[currentIndex].fIPAddrStr.Len = ::strlen(theAddrStr);        sIPAddrInfoArray[currentIndex].fIPAddrStr.Ptr = new char[sIPAddrInfoArray[currentIndex].fIPAddrStr.Len + 2];        ::strcpy(sIPAddrInfoArray[currentIndex].fIPAddrStr.Ptr, theAddrStr);                struct hostent* theDNSName = NULL;        if (lookupDNSName) //convert this addr to a dns name, and store it        {   theDNSName = ::gethostbyaddr((char *)&theAddr->sin_addr, sizeof(theAddr->sin_addr), AF_INET);        }                if (theDNSName != NULL)        {            sIPAddrInfoArray[currentIndex].fDNSNameStr.Len = ::strlen(theDNSName->h_name);            sIPAddrInfoArray[currentIndex].fDNSNameStr.Ptr = new char[sIPAddrInfoArray[currentIndex].fDNSNameStr.Len + 2];            ::strcpy(sIPAddrInfoArray[currentIndex].fDNSNameStr.Ptr, theDNSName->h_name);        }        else        {            //if we failed to look up the DNS name, just store the IP addr as a string            sIPAddrInfoArray[currentIndex].fDNSNameStr.Len = sIPAddrInfoArray[currentIndex].fIPAddrStr.Len;            sIPAddrInfoArray[currentIndex].fDNSNameStr.Ptr = new char[sIPAddrInfoArray[currentIndex].fDNSNameStr.Len + 2];            ::strcpy(sIPAddrInfoArray[currentIndex].fDNSNameStr.Ptr, sIPAddrInfoArray[currentIndex].fIPAddrStr.Ptr);        }        //move onto the next array index        currentIndex++;            }#ifdef __Win32__    ::closesocket(tempSocket);#elif defined(USE_SIOCGIFNUM)    delete[] ifc.ifc_buf;    ::close(tempSocket);#else#error#endif    #else // !__Win32__    //Most of this code is similar to the SIOCGIFCONF code presented in Stevens,    //Unix Network Programming, section 16.6        //Use the SIOCGIFCONF ioctl call to iterate through the network interfaces    static const UInt32 kMaxAddrBufferSize = 20480;		//modify by puzy         struct ifconf ifc;    ::memset(&ifc,0,sizeof(ifc));    struct ifreq* ifr;    char buffer[kMaxAddrBufferSize];        int tempSocket = ::socket(AF_INET, SOCK_DGRAM, 0);    if (tempSocket == -1)        return;            ifc.ifc_len = kMaxAddrBufferSize;    ifc.ifc_buf = buffer;#if __linux__     int err = ::ioctl(tempSocket, SIOCGIFCONF, (char*)&ifc);#else    #error#endif    if (err == -1)        return;        ::close(tempSocket);    tempSocket = -1;    //walk through the list of IP addrs twice. Once to find out how many,    //the second time to actually grab their information    char* ifReqIter = NULL;    sNumIPAddrs = 0;        for (ifReqIter = buffer; ifReqIter < (buffer + ifc.ifc_len);)    {        ifr = (struct ifreq*)ifReqIter;        if (!SocketUtils::IncrementIfReqIter(&ifReqIter, ifr))            return;                // Some platforms have lo as the first interface, so we have code to        // work around this problem below        //if (::strncmp(ifr->ifr_name, "lo", 2) == 0)        //  Assert(sNumIPAddrs > 0); // If the loopback interface is interface 0, we've got problems            //Only count interfaces in the AF_INET family.        if (ifr->ifr_addr.sa_family == AF_INET)            sNumIPAddrs++;    }       //allocate the IPAddrInfo array. Unfortunately we can't allocate this    //array the proper way due to a GCC bug    UInt8* addrInfoMem = new UInt8[sizeof(IPAddrInfo) * sNumIPAddrs];    ::memset(addrInfoMem, 0, sizeof(IPAddrInfo) * sNumIPAddrs);    sIPAddrInfoArray = (IPAddrInfo*)addrInfoMem;        //Now extract all the necessary information about each interface    //and put it into the array    UInt32 currentIndex = 0; 	    for (ifReqIter = buffer; ifReqIter < (buffer + ifc.ifc_len);)    {        ifr = (struct ifreq*)ifReqIter;        if (!SocketUtils::IncrementIfReqIter(&ifReqIter, ifr))        {            Assert(0);//we should have already detected this error            return;        }                //Only count interfaces in the AF_INET family        if (ifr->ifr_addr.sa_family == AF_INET)        {            struct sockaddr_in* addrPtr = (struct sockaddr_in*)&ifr->ifr_addr;              char* theAddrStr = ::inet_ntoa(addrPtr->sin_addr);            //store the IP addr            sIPAddrInfoArray[currentIndex].fIPAddr = ntohl(addrPtr->sin_addr.s_addr);                        //store the IP addr as a string            sIPAddrInfoArray[currentIndex].fIPAddrStr.Len = ::strlen(theAddrStr);            sIPAddrInfoArray[currentIndex].fIPAddrStr.Ptr = new char[sIPAddrInfoArray[currentIndex].fIPAddrStr.Len + 2];            ::strcpy(sIPAddrInfoArray[currentIndex].fIPAddrStr.Ptr, theAddrStr);            struct hostent* theDNSName = NULL;            if (lookupDNSName) //convert this addr to a dns name, and store it            {   theDNSName = ::gethostbyaddr((char *)&addrPtr->sin_addr, sizeof(addrPtr->sin_addr), AF_INET);            }                        if (theDNSName != NULL)            {                sIPAddrInfoArray[currentIndex].fDNSNameStr.Len = ::strlen(theDNSName->h_name);                sIPAddrInfoArray[currentIndex].fDNSNameStr.Ptr = new char[sIPAddrInfoArray[currentIndex].fDNSNameStr.Len + 2];                ::strcpy(sIPAddrInfoArray[currentIndex].fDNSNameStr.Ptr, theDNSName->h_name);            }            else            {                //if we failed to look up the DNS name, just store the IP addr as a string                sIPAddrInfoArray[currentIndex].fDNSNameStr.Len = sIPAddrInfoArray[currentIndex].fIPAddrStr.Len;                sIPAddrInfoArray[currentIndex].fDNSNameStr.Ptr = new char[sIPAddrInfoArray[currentIndex].fDNSNameStr.Len + 2];                ::strcpy(sIPAddrInfoArray[currentIndex].fDNSNameStr.Ptr, sIPAddrInfoArray[currentIndex].fIPAddrStr.Ptr);            }                        //move onto the next array index            currentIndex++;        }    }        Assert(currentIndex == sNumIPAddrs);#endif    //    // If LocalHost is the first element in the array, switch it to be the second.    // The first element is supposed to be the "default" interface on the machine,    // which should really always be en0.    if ((sNumIPAddrs > 1) && (::strcmp(sIPAddrInfoArray[0].fIPAddrStr.Ptr, "127.0.0.1") == 0))    {        UInt32 tempIP = sIPAddrInfoArray[1].fIPAddr;        sIPAddrInfoArray[1].fIPAddr = sIPAddrInfoArray[0].fIPAddr;        sIPAddrInfoArray[0].fIPAddr = tempIP;        StrPtrLen tempIPStr(sIPAddrInfoArray[1].fIPAddrStr);        sIPAddrInfoArray[1].fIPAddrStr = sIPAddrInfoArray[0].fIPAddrStr;        sIPAddrInfoArray[0].fIPAddrStr = tempIPStr;        StrPtrLen tempDNSStr(sIPAddrInfoArray[1].fDNSNameStr);        sIPAddrInfoArray[1].fDNSNameStr = sIPAddrInfoArray[0].fDNSNameStr;        sIPAddrInfoArray[0].fDNSNameStr = tempDNSStr;    }}
void SocketUtils::Uninitialize()
{
	// delete IPAddress array
    for (UInt32 i = 0 ; i< sNumIPAddrs; i++)
	{
		if(sIPAddrInfoArray[i].fIPAddrStr.Len != 0)
			delete[] sIPAddrInfoArray[i].fIPAddrStr.Ptr;
		if(sIPAddrInfoArray[i].fDNSNameStr.Len != 0)
			delete[] sIPAddrInfoArray[i].fDNSNameStr.Ptr;
	}
	// since sIPAddrInfoArray is allocated by UInt8 array
	// so delete as UInt8 array
	delete[] (UInt8 *)sIPAddrInfoArray;
}

#ifndef __Win32__Bool SocketUtils::IncrementIfReqIter(char** inIfReqIter, ifreq* ifr){    //returns true if successful, false otherwise    *inIfReqIter += sizeof(ifr->ifr_name) + 0;    {        switch (ifr->ifr_addr.sa_family)        {            case AF_INET:                *inIfReqIter += sizeof(struct sockaddr_in);                break;            default:                *inIfReqIter += sizeof(struct sockaddr);//              Assert(0);//              sNumIPAddrs = 0;//              return false;        }    }    return true;}#endifBool SocketUtils::IsMulticastIPAddr(UInt32 inAddress){    return ((inAddress>>8) & 0x00f00000) == 0x00e00000; //  multicast addresses == "class D" == 0xExxxxxxx == 1,1,1,0,<28 bits>}Bool SocketUtils::IsLocalIPAddr(UInt32 inAddress){    for (UInt32 x = 0; x < sNumIPAddrs; x++)        if (sIPAddrInfoArray[x].fIPAddr == inAddress)            return true;    return false;}void SocketUtils::ConvertAddrToString(const struct in_addr& theAddr, string* ioStr){	*ioStr= inet_ntoa(theAddr);}UInt32 SocketUtils::ConvertStringToAddr(const char* inAddrStr){    return ntohl(::inet_addr(inAddrStr));}Bool SocketUtils::GetPeerInfo( Int32 vFD, std::string & vIP, UInt16 & vPort ){	struct sockaddr_in  fRemoteAddr;#if __Win32__ 	        int len = sizeof(fRemoteAddr);#else        socklen_t len = sizeof(fRemoteAddr);#endif	len=sizeof(fRemoteAddr);	int err=::getpeername(vFD,(struct sockaddr*)&fRemoteAddr,&len);	if(err != 0) return FALSE;	vIP = inet_ntoa(fRemoteAddr.sin_addr);	vPort = ntohs(fRemoteAddr.sin_port);	return TRUE;}
//域名解析
UInt32 SocketUtils::HostNameToIP(const std::string& strHostName){
	long lHostIp = 0;
	struct hostent *psHost = NULL;
	struct sockaddr_in saddr;
	
	lHostIp = 0;
	psHost = NULL;
	
	memset(&saddr, 0, sizeof(struct sockaddr_in));
	
	if ( ( lHostIp = inet_addr(strHostName.c_str()) ) != INADDR_NONE ) 
	{
		saddr.sin_addr.s_addr = lHostIp;
	} 
	else if ( psHost = gethostbyname(strHostName.c_str()) ) 
	{
		memcpy(&saddr.sin_addr, psHost->h_addr, psHost->h_length);
	} 
	else 
	{
		printf("Failed getting Up server's IP with DNS");
	}
	
	return ntohl(saddr.sin_addr.s_addr);
}

std::string SocketUtils::HostNameToStringIP(const std::string& strHostName)
{
	UInt32 nIP = HostNameToIP(strHostName);
	return IPAddrToString(nIP);
}

std::string SocketUtils::IPAddrToString(unsigned long nIpAddr)
{
	in_addr tmpAdd;
	tmpAdd.s_addr = htonl(nIpAddr);
	return inet_ntoa(tmpAdd);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -