精简版inet_addr

精简版inet_addr

CooCox Cedar@Wuhan




说明:


 今天在移植代码的时候,需要一个客户端WiFiClientConnect函数,该函数的一个参数为服务器地址,第二个为端口。

其中服务器的地址可以是主机地址(如: www.baidu.com ),也可以是IP地址(如:192.168.2.71)。

官方的WIFI驱动是C++重载函数写的,可以根据不同的输入格式来调用对应的函数,C中没有重载,只有手工解析,解决方法有3个:

1:分别采用2个函数,比如提供WiFiClientConnectVia 和Host WiFiClientConnectViaIP两个函数,供用户调用

2:像Arduino WiFi驱动接口那样,使用一个函数,但增加一个入口参数,用于指明服务器地址类型

3:符合Arduino 官方WIFI的调用习惯,用一个WiFiClientConnect函数,用户只需输入HOST或IP即可,解析的问题,交给函数内部来处理如 WiFiConnect( "www.baidu.com", 80);WiFiConnect( "192.168.2.71", 80)

最终为了方便用户,采用了最后一个方案,这样用户可以更加方便的使用WIFI

我们需要在内部识别出是否是有效的IP地址,如果是的话,则转换为网络地址,这样就需要一个识别和转换函数IPToNetAddr。

IPToNetAddr将传入的IP地址解析成网络格式,比如将“192.168.2.71”分割成4个10进制的数字,存到数组里面

在Q群问了网友,有人说inet_addr符合要求,找到对应源码后,发现它考虑的情况太多了,支持各种进制的数字,而我们这里,只需要支持10进制就ok,网上搜了一下,貌似没人写过这函数,所以还是自己动手写一个吧


要求


1:能识别出输入IP字符串是否有效,有效则返回0,无效则返回-1
2:输入错误的IP地址,函数不损坏存放结果的数组

错误的IP例子:
1: 子项过大:每个子项应小于255。下面的IP地址第一个子项为1921,大于255
    1921.108.2.71 
2: 子项过多:应有4个子项,由3个.号分隔,下面的IP地址有5个子项
    192.168.2.1.2


测试代码如下:

int main(void)
{
    int retv = 0;

    //目标IP地址字符串
    char IP_OK[] = "192.168.002.071";
    char IP_ERROR_1[] = "1921.108.2.71";
    char IP_ERROR_2[] = "192.168.2.1.2";
    char IP_ERROR_3[] = "293.168.2.1.2";
    char IP_ERROR_4[] = "193.168.2.1.300";

    //存储结果数组
    uint8_t result[4] = {0, 0, 0, 0};

    retv = IPToNetAddr(IP_OK, result);    
    if(-1 == retv)
    {
        printf("Test Failure\r\n");
        while(1);
    }

    retv = IPToNetAddr(IP_ERROR_1, result);    
    if(0 == retv)
    {
        printf("Test Failure\r\n");
        while(1);
    }

    retv = IPToNetAddr(IP_ERROR_2, result);    
    if(0 == retv)
    {
        printf("Test Failure\r\n");
        while(1);
    }

    retv = IPToNetAddr(IP_ERROR_3, result);    
    if(0 == retv)
    {
        printf("Test Failure\r\n");
        while(1);
    }

    retv = IPToNetAddr(IP_ERROR_3, result);    
    if(0 == retv)
    {
        printf("Test Failure\r\n");
        while(1);
    }

    printf("Test OK, Press any key to exit\r\n");
    getchar();
    
    return (0);
}




完整代码如下:

CODE:

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
//#include <stdint.h>
#include <string.h>

typedef unsigned char uint8_t;
typedef signed   char int8_t;

typedef unsigned int  uint32_t;
typedef signed   int  int32_t;

int IPToNetAddr(char * IPStr, uint8_t * NetAddr);

int main(void)
{
    int retv = 0;

    //目标IP地址字符串
    char IP_OK[] = "192.168.002.071";
    char IP_ERROR_1[] = "1921.108.2.71";
    char IP_ERROR_2[] = "192.168.2.1.2";
    char IP_ERROR_3[] = "293.168.2.1.2";
    char IP_ERROR_4[] = "193.168.2.1.300";

    //存储结果数组
    uint8_t result[4] = {0, 0, 0, 0};

    retv = IPToNetAddr(IP_OK, result);    
    if(-1 == retv)
    {
        printf("Test Failure\r\n");
        while(1);
    }

    retv = IPToNetAddr(IP_ERROR_1, result);    
    if(0 == retv)
    {
        printf("Test Failure\r\n");
        while(1);
    }

    retv = IPToNetAddr(IP_ERROR_2, result);    
    if(0 == retv)
    {
        printf("Test Failure\r\n");
        while(1);
    }

    retv = IPToNetAddr(IP_ERROR_3, result);    
    if(0 == retv)
    {
        printf("Test Failure\r\n");
        while(1);
    }

    retv = IPToNetAddr(IP_ERROR_4, result);    
    if(0 == retv)
    {
        printf("Test Failure\r\n");
        while(1);
    }

    printf("Test OK, Press any key to exit\r\n");
    getchar();
    
    return (0);
}

int IPToNetAddr(char * IPStr, uint8_t * NetAddr)
{
    uint32_t _IP[4] = {0, 0, 0, 0};
    uint8_t cnt = 0;
    uint8_t idx = 0;
    char _str = NULL;
    
    //检查IP和接收缓存区是否有效
    if(IPStr == NULL || NetAddr == NULL)
    {
        return (-1);
    }

    while((_str = *IPStr++) != NULL)
    {
        if(_str == '.')
        {
            //清空计数器,该计数器最大值为3
            cnt = 0;            
            if(_IP[idx] > 255)
            {
                return (-1);
            }
            idx = idx + 1;
        }
        else if(_str >= '0' && _str <= '9')  //检查是否为有效字符 '0' --> '9'
        {            
            if(cnt++ < 3 && idx <= 3)
            {
                _IP[idx] = (10 * _IP[idx]) + (_str - '0');
            }
            else
            {
                return (-1);
            }
        }
        else
        {
            return (-1);
        }
    }

    if(_IP[idx] > 255)
    {
        return (-1);
    }

    //复制数据到结果缓存区
    NetAddr[0] = (uint8_t)_IP[0];
    NetAddr[1] =  (uint8_t) _IP[1];
    NetAddr[2] =  (uint8_t) _IP[2];
    NetAddr[3] =  (uint8_t) _IP[3];

    return (0);
}





英文版本:



static int IPToNetAddr(char * IPStr, uint8_t * NetAddr)
{
    uint32_t _IP[4] = {0, 0, 0, 0};
    uint8_t cnt = 0;
    uint8_t idx = 0;
    char _str = NULL;
    
    // Check input paramters vaild
    if(IPStr == NULL || NetAddr == NULL)
    {
        return (-1);
    }

    while((_str = *IPStr++) != NULL)
    {
        if(_str == '.')
        {
            // Clear the count, cnt MUST <= 3
            cnt = 0;            
            if(_IP[idx] > 255)
            {
                return (-1);
            }
            idx = idx + 1;
        }
        else if(_str >= '0' && _str <= '9')  // '0' --> '9'
        {            
            if(cnt++ < 3 && idx <= 3)
            {
                _IP[idx] = (10 * _IP[idx]) + (_str - '0');
            }
            else
            {
                return (-1);
            }
        }
        else
        {
            return (-1);
        }
    }

    if(_IP[idx] > 255)
    {
        return (-1);
    }

    // Copy Buffer to user space
    NetAddr[0] = (uint8_t)_IP[0];
    NetAddr[1] = (uint8_t)_IP[1];
    NetAddr[2] = (uint8_t)_IP[2];
    NetAddr[3] = (uint8_t)_IP[3];

    return (0);
}


#本文结束#

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值