struct sockaddr和struct sockaddr_in

Socket.h文件中struct sockaddr的定义如下所示:

/*
 * Structure used by kernel to store most
 * addresses.
 */
struct sockaddr {
	u_char		sa_len;		/* total length */
	sa_family_t	sa_family;	/* address family */
	char		sa_data[14];	/* actually longer; address value */
};

In.h文件中struct sockaddr_in的定义如下所示:

struct in_addr {
	in_addr_t s_addr;	//in_addr_t为无符号int类型,4个字节
};

/*
 * Socket address, internet style.
 */
struct sockaddr_in {
	u_char	sin_len;
	u_char	sin_family;
	u_short	sin_port;
	struct	in_addr sin_addr;
	char	sin_zero[8];
};

可以看到struct sockaddrstruct sockaddr_in都是16个字节,而且是一一对应的关系。所以,这两个结构体的转化使用强制类型转化就可以。

在堆叠项目的rpc设计中,则可以使用char tmp[16]的字符数组存放这两个结构体,用于rip路由表的同步。

下面是结构体struct in_addr的应用实例,一个UINT32的IP地址,需要转化为a.b.c.d的字符串格式。

	UINT32 ip = 0x010101010;
	char ipAddr[20] = {0};
	struct in_addr iaddr;
	
	iaddr.s_addr = ip;
	inet_ntoa_b (iaddr, ipAddr);

OSPF中字符串转化为IP地址或者数字

OSPF中的区域ID既可以是数字,又可以是IP地址形式(a.b.c.d)。cli输入该字符串之后,需要获取其数值,存放到UINT 32的整型变量中。

第一次撰写的代码如下,IP地址字符串和数字字符串全部手动解析。

/*!
 *\fn			STATUS ospfStr2int()
 *\brief		convert the string to int
 *\details		the string must be ip address or pure int string
 *\param[in]	
 *
 *\note		
 *\author	NieYong <NieYong@tp-link.net>
 */
STATUS ospfStr2int(char* p,UINT32 * ipAddr)
{
	UINT8 flg = 0;
	UINT8 nLen;
	INT16 nTemp = 0;
	UINT8 nPosition = 0;
	UINT8 cIp[4];
	char *pszIp;
	UINT32 num = 0;

	if (NULL != p)
    { 
		while (*p != '\0' && isspace((int)*p) != 0) 
		{
			p++; 
		}
	}

	/* printf("ospfStr2int:%s\n",p); */

	pszIp = p;
	nLen = strlen(pszIp);
	if((NULL == pszIp) ||(nLen > IP_ADDRESS_LENGTH))
	{
		return ERROR;
	}

	/* first,we check if the string is int number string */
	while(flg != 1 && *pszIp != '\0')
	{
		switch(*pszIp)
		{
			case '0':		
			case '1':
			case '2':		
			case '3':
			case '4':		
			case '5':
			case '6':		
			case '7':
			case '8':		
			case '9':
				num = num * 10 + *pszIp - '0';
				break;
			default:
				flg = 1;
				break;
		}
		pszIp++;
	}

	if(flg != 1)
	{
		/* we're here,meant the ip address string is right */
		* ipAddr = num;
		/* printf("ospfStr2int:%d\n",* ipAddr); */
		return OK;
	}

	/* if the check above failed,we should check if the string is 
	   ip address sting secondly */
   pszIp = p;
	while(*pszIp != '\0')
	{
		switch(*pszIp)
		{
			case '0':		
			case '1':
			case '2':		
			case '3':
			case '4':		
			case '5':
			case '6':		
			case '7':
			case '8':		
			case '9':
				nTemp = nTemp * 10 + *pszIp - '0';
				if(nTemp > 255)
				{
					return ERROR;
				}
				break;
			case '.':

				/* except case :  192..0.1 */
				if( '.' == *(pszIp + 1))
				{
					return ERROR;
				}

				/* except case : 192.168.0.1.5 */
				if(3 == nPosition)
				{
					return ERROR;
				}
				
				//store the ipaddress
				cIp[nPosition] = nTemp; 
				nPosition ++;
				nTemp = 0;
				break;
			default:
				return ERROR;
				break;
		}
		pszIp++;
	}

	if(nPosition == 3)
	{
		/* we're here,meant the ip address string is right */
		cIp[nPosition] = nTemp;
		*ipAddr = (cIp[0]<<24) + (cIp[1]<<16) + (cIp[2]<<8) + cIp[3];
		/* printf("ospfStr2int:%d\n",* ipAddr); */
		return OK;
	}
	else
	{
		return ERROR;
	}
}

修改之后,对于ip地址类型字符串的解析直接使用函数inet_aton(),这样可以避免不少问题。代码如下:

/*!
 *\fn			STATUS swOspfStr2int()
 *\brief		convert the string to int
 *\details		the string must be ip address or pure int string
 *\param[in]	
 *
 *\note		
 *\author	NieYong <NieYong@tp-link.net>
 */
STATUS swOspfStr2int(char* p,UINT32 * ipAddr)
{
	UINT8 flg = 0;
	UINT8 nLen;
	INT16 nTemp = 0;
	UINT8 nPosition = 0;
	UINT8 cIp[4];
	char *pszIp;
	UINT32 num = 0;

	struct in_addr inAddr;

	if (NULL != p)
    { 
		while (*p != '\0' && isspace((int)*p) != 0) 
		{
			p++; 
		}
	}

	OSPF_DBG_PRINT("swOspfStr2int:%s\n",p);

	pszIp = p;
	nLen = strlen(pszIp);
	if((NULL == pszIp) ||(nLen > IP_ADDRESS_LENGTH))
	{
		return ERROR;
	}

	/* first check if the string is ip dot notation style */
	if(inet_aton(pszIp,&inAddr))
	{
		/* the string is dot notation style */
		ipAddr = inAddr.s_addr;
		return OK;
	}

	/* if the string is not dot notation,we should check if 
	 * the string is int number string.
	 */
	while(flg != 1 && *pszIp != '\0')
	{
		switch(*pszIp)
		{
			case '0':		
			case '1':
			case '2':		
			case '3':
			case '4':		
			case '5':
			case '6':		
			case '7':
			case '8':		
			case '9':
				num = num * 10 + *pszIp - '0';
				break;
			default:
				flg = 1;
				break;
		}
		pszIp++;
	}

	if(flg != 1)
	{
		/* we're here,meant the ip address string is right */
		* ipAddr = num;
		OSPF_DBG_PRINT("ospfStr2int:%d\n",* ipAddr);
		return OK;
	}
	else
	{
		return ERROR;
	}
}