【轉】Arduino官方WIFI模塊----開(kāi)發(fā)記錄

發(fā)布時(shí)間:2012-12-24 08:59    發(fā)布者:coocox
關(guān)鍵詞: Arduino , WIFI , Cookie , Cox
WIFI開(kāi)發(fā)計劃

CooCox Cedar@Wuhan


說(shuō)明:
本來(lái)計劃開(kāi)發(fā)SparkFun的WiFly模塊,后來(lái)發(fā)現Arduino官網(wǎng)出了WIFI模塊,就優(yōu)先開(kāi)發(fā)Arduino WIFI Shield。

官方的WIFI Shield資料如下:
*:原理圖
*:PCB文件
*:WIFI庫
*:固件代碼(用于實(shí)現IP棧)
以上所有資料均可從Arduino官網(wǎng)下載,需要說(shuō)明的是WIFI Shield的核心芯片是HDG104,進(jìn)入HD官網(wǎng)下載資料時(shí),

需要注冊賬戶(hù),注冊后,不知為何,始終無(wú)法登陸,所有沒(méi)有下載到任何手冊。如果您有HDG104的手冊,可以分享
一下,非常感謝。

因為換WIFI模塊,需要重新熟悉代碼和資料,現制定一份初步計劃
計劃如下:


  階段1:  
學(xué)習Socket編程

難點(diǎn):開(kāi)發(fā)環(huán)境的搭建,熟悉網(wǎng)絡(luò )概念


階段
2:
用Socket實(shí)現HTTP例子(客戶(hù)端和服務(wù)器)

難點(diǎn):HTTP協(xié)議分析和HTML代碼編寫(xiě)


階段
3:
分析官方WIFI庫代碼

難點(diǎn):理解代碼的分層模型,從代碼中分析WIFI模塊的協(xié)議


階段
4:
移植到Cookie

難點(diǎn):Cox接口入門(mén)

                       
階段
5:
總結

總結心得體會(huì ),分享資料,鏈接





PS:如果有任何疑問(wèn),請跟帖或email我,3Q
Email: renjun@coocox.com


Socket軟件包使用說(shuō)明



綜述


本Socket軟件包作為Arduino WIFI shield入門(mén)指導中的一部分,用于說(shuō)明如何在windows下用TCP/IP Socket編程,如何建立鏈接,綁定端口,收發(fā)數據,深入理解這部分,更利于后期學(xué)習HTTP客戶(hù)端和服務(wù)器代碼。這里用Socket寫(xiě)了一個(gè)簡(jiǎn)單的局域網(wǎng)聊天工具,在不同的機器上分別運行客戶(hù)端和服務(wù)器,然后就像QQ一樣聊天。


軟硬件環(huán)境


操作系統: Win7
開(kāi)發(fā)環(huán)境: VS2008
開(kāi)發(fā)語(yǔ)言:C
注:所有代碼在上述環(huán)境中測試通過(guò),理論上在其它環(huán)境(如VC++6.0,windows XP)可以編譯通過(guò),但未測試


目錄結構


使用時(shí)只需要重點(diǎn)關(guān)注紅色字體標注的文件(夾)

Socket
│  
├─client
│  │  client.c                                   ------> Socket 客戶(hù)端源碼
│  │  
│  ├─client
│  │  │  client.ncb
│  │  │  client.sln
│  │  │  client.vcproj                           ------> Client VC工程文件
│  │  │  client.vcproj.RENJUN-PC.RENJUN.user
│  │  │  
│  │  └─Debug
│  │          BuildLog.htm
│  │          client.exe                         ------> VC工程生成的客戶(hù)端可執行文件,在本
│  │                                                     機上可以直接雙擊運行。如需在其它電腦運行,
│  │                                                     請參考“發(fā)布”章節中的步驟和注意事項
│  │          client.exe.embed.manifest          ------> exe文件的依賴(lài)關(guān)系,詳細信息,參考“發(fā)布”章節
│  │          client.exe.embed.manifest.res
│  │          client.exe.intermediate.manifest
│  │          client.ilk
│  │          client.obj
│  │          client.pdb
│  │          mt.dep
│  │          vc90.idb
│  │          vc90.pdb
│  │         
│  └─dist                                        ------> 需要在其它沒(méi)裝VS2008的電腦上運行exe文件時(shí),
│      │                                                 直接將dist文件夾復制過(guò)去就ok,
│      │                                                 詳細信息,參見(jiàn)“發(fā)布”章節
│      │  client.exe
│      │  client.exe.embed.manifest
│      │  
│      └─Microsoft.VC90.DebugCRT
│              Microsoft.VC90.DebugCRT.manifest
│              msvcm90d.dll
│              msvcp90d.dll
│              msvcr90d.dll
│              
└─server
    │  server.c                                  ------> Socket 服務(wù)器源碼
    │  
    ├─dist                                       ------> 需要在其它沒(méi)裝VS2008的電腦上運行exe文件時(shí),
    │  │                                                 直接將dist文件夾復制過(guò)去就ok
    │  │                                                 詳細信息,參見(jiàn)“發(fā)布”章節
    │  │  server.exe
    │  │  server.exe.embed.manifest
    │  │  
    │  └─Microsoft.VC90.DebugCRT
    │          Microsoft.VC90.DebugCRT.manifest
    │          msvcm90d.dll
    │          msvcp90d.dll
    │          msvcr90d.dll
    │         
    └─server
        │  server.ncb
        │  server.sln
        │  server.vcproj                           ------> Server VC工程文件
        │  server.vcproj.RENJUN-PC.RENJUN.user
        │  
        └─Debug
                BuildLog.htm
                mt.dep
                server.exe                         ------> VC工程生成的客戶(hù)端可執行文件,在本機上
                                                           可以直接雙擊運行。如需在其它電腦運行,
                                                           請參考“發(fā)布”章節中的步驟和注意事項
                server.exe.embed.manifest          ------> exe文件的依賴(lài)關(guān)系,詳細信息,參考“發(fā)布”章節
                server.exe.embed.manifest.res
                server.exe.intermediate.manifest
                server.ilk
                server.obj
                server.pdb
                vc90.idb
                vc90.pdb







使用方法


A:體驗
1:雙擊打開(kāi)server 目錄下exe文件夾下exe文件,啟動(dòng)聊天服務(wù)器
2:雙擊打開(kāi)client 目錄下exe文件夾下exe文件,啟動(dòng)聊天客戶(hù)端
3:?jiǎn)?dòng)客戶(hù)端后,輸入服務(wù)器主機IP地址,便可開(kāi)始聊天
4:根據提示進(jìn)行發(fā)送和接收信息,在發(fā)送狀態(tài)時(shí),如果不想發(fā)送數據,可以按回車(chē),取消發(fā)送

B:開(kāi)發(fā)
1:確保您已經(jīng)正確安裝VS2008
     2:雙擊軟件包中的server.vcproj和client.vcproj,打開(kāi)對應的工程文件
     3:編譯和調試server和client代碼




發(fā)布



如果想要將生成的exe文件在其他電腦上運行,只復制exe文件過(guò)去,打開(kāi)時(shí),會(huì )出現下面的錯誤


file:///C:/Users/RENJUN/AppData/Local/youdao/ynote/images/6286383C8E6B40F6B8A017F7F6E13A14/R%5DQEAS%257BW%40)%40%5B8QENKYFPA67.jpg




這是因為缺少對應的dll,所以我們需要同時(shí)復制dll,exe和描述文件過(guò)去,別人才能正常運行

這里以打包c(diǎn)lient為例,來(lái)說(shuō)明如何正確發(fā)布軟件
1:新建一個(gè)文件夾,文件夾名字隨便起,這里我們將文件夾命名為dist,該文件夾用于存放exe文件和對應的依賴(lài)文件
2:打開(kāi)軟件包中Debug文件夾,找到 client .exe和 client .exe.embed.manifest文件
   如沒(méi)有這些文件,進(jìn)入VS2008,rebuild一下
3:打開(kāi) client.exe.embed.manifest文件,查看exe依賴(lài)的dll
   在我電腦上,client.exe.embed.manifest內容如下:




  
   
      
        
      
   
  
  
   
      
   
  



文件組織方式為標準xml結構,在此重點(diǎn)關(guān)注部分(紅色字體)?梢缘玫饺缦滦畔ⅲ
  • 該exe為win32可執行文件
  • 依賴(lài)Microsoft.VC90.DebugCRT目錄下的dll文件
  • dll版本號為:9.0.21022.8

知道缺少了哪些dll,只需要將這些dll復制到exe文件夾下即可


4:進(jìn)入VS2008安裝目錄,找到Microsoft.VC90.DebugCRT這個(gè)文件夾,在我的電腦上路徑如下:
   D:\Program Files\Microsoft Visual Studio 9.0\VC\redist\Debug_NonRedist\x86
   不同電腦,路徑可能不一樣,但大致結構相同


5:將Microsoft.VC90.DebugCRT文件夾整體拷貝到第1步建立的dist文件夾中


6:現在所有的必須的文件都已經(jīng)復制完畢,dist文件夾下目錄組織結構如下

dist
|-->client.exe
|-->client.exe.embed.manifest  
|---Microsoft.VC90.DebugCRT
      |---> Microsoft.VC90.DebugCRT.manifest
      |---> msvcm90d.dll
      |---> msvcp90d.dll
      |---> msvcr90d.dll




7:檢查dist目錄下client.exe.embed.manifest和Microsoft.VC90.DebugCRT.manifest版本號(9.0.21022.8)是否一致

8:現在您可以將dist文件夾打包,發(fā)送給朋友了 ^_^


軟件包下載




所有代碼可以從github網(wǎng)站下載:
https://github.com/cedar-renjun/Socket_server_client_chat_Example






Socket Http WebClient






說(shuō)明:直接用Socket連接百度web服務(wù)器,然后發(fā)送HTTP Get請求來(lái)獲取百度首頁(yè),VS2008工程在上個(gè)帖子中有鏈接,這次直接發(fā)代碼,使用時(shí),將代碼復制到.c文件中,rebuild生成exe文件,然后點(diǎn)擊運行,就可以看到獲取的html網(wǎng)頁(yè)了

#include
#include
#include

// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")

#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT 80

WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
char *HttpRequst ="GET / HTTP/1.1\r\nConnection: close\r\n\r\n";
char RecvBuf[DEFAULT_BUFLEN];
char *IP = "119.75.217.56";
struct sockaddr_in ServerCfg;
char WelcomeInfo[] =
{
    "\t===============WIFI Shield Dirver================\r\n"
    "\tName: HTTP WebClient Example\r\n"
    "\tHOST : http://www.baidu.com\r\n"
    "\tIP   : 119.75.217.56\r\n"
    "\tPORT : 80\r\n"
    "\t=============== CooCox Team =====================\r\n"
};

int main(void)
{
    int tmp = 0;
    int cnt = 0;
    int iResult = 0;

    printf(WelcomeInfo);
    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != 0)
        {
        printf("WSAStartup failed with error: %d\r\n", iResult);
        return 1;
    }
    printf("Initial WinSock OK\r\r\n");

    // Create a SOCKET for connecting to server
    ConnectSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (ConnectSocket  == INVALID_SOCKET)
    {
        printf("socket failed with error: %ld\r\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }
    printf("Create Socket OK\r\n");

    //Connect to Server
    ServerCfg.sin_family = AF_INET;
    ServerCfg.sin_port = htons(DEFAULT_PORT);
    ServerCfg.sin_addr.s_addr = inet_addr(IP);

    printf("Try to connect server\r\n");
    iResult = connect(ConnectSocket, (struct sockaddr *)&ServerCfg, sizeof(struct sockaddr));
    if (iResult == SOCKET_ERROR)
    {
        printf("Unable to connect to server!\n");
        WSACleanup();
        return 1;
    }
    printf("Connect to server!\r\n");   
    // Send Message to Server

    printf("Send HTTP Requst\r\n%s", HttpRequst);

    iResult = send( ConnectSocket, HttpRequst, strlen(HttpRequst), 0);
    if (iResult == SOCKET_ERROR)
    {
        printf("send failed with error: %d\r\n", WSAGetLastError());
    }

    printf("-----------Receive Respon Message---------\r\n");

    // Receive Full response message
    while(1)
    {
        // Important,MUST NOT comment this
        memset(RecvBuf, '\0', DEFAULT_BUFLEN);
        iResult = recv( ConnectSocket, RecvBuf, DEFAULT_BUFLEN, 0);
        if (iResult < 0)
        {
            printf("receive failed with error: %d\r\n", WSAGetLastError());
        }
        else if(iResult > 0)
        {
            puts(RecvBuf);
        }
        else
        {
            printf("\r\n----------------------------------------------");
            printf("\r\nReceive OK\r\n");
            break;
        }
    }

    // clean
    printf("Now Release resource\r\n");
    closesocket(ConnectSocket);
    WSACleanup();
    printf("Closed! Example is over\r\n");
    printf("Press Enter to exit\r\n");
    getch();
    //while(1);
}



Socket Http WebServer







#include
#include     // use Sleep function
#include
#include
#include

// Need to link with Ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")

#define DEFAULT_BUFLEN 2048
#define DEFAULT_PORT 27013

char RecvBuf[DEFAULT_BUFLEN];
char SendBuf[DEFAULT_BUFLEN];

struct sockaddr_in ServerCfg;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
char WelcomeInfo[] =
{   
    "\t===============WIFI Shield Dirver================\r\n"
        "\tName: TCP Socket Http Webserver Example\r\n"
        "\tPORT : 8080\r\n"
        "\t=============== CooCox Team =====================\r\n"
};

char RespondInfo[] =
{
    "HTTP/1.1 200 OK\r\n"   
        "Content-Type: text/html\r\n"
        "Connnection: close\r\n"
        "\r\n"
        "\r\n"
        "\r\n"   
        "\r\n"
        "

"
        "================= WIFI Shield Dirver===============
"
        "Name: TCP Socket Http Webserver Example
"
        "PORT : 27013
"
        "==================="
        "CooCox Team
=====================
"
        "

"
        " 午夜高清国产拍精品福利|亚洲色精品88色婷婷七月丁香|91久久精品无码一区|99久久国语露脸精品|动漫卡通亚洲综合专区48页

\r\n"
        "\r\n"
        "\r\n"
};

int main(void)
{
    WSADATA wsaData;
    int iResult = 0;
    int iSendResult = 0;
    printf(WelcomeInfo);
    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != 0)
    {
        printf("WSAStartup failed with error: %d\n", iResult);
        return 1;
    }
    printf("Initial WinSock OK\r\n");

    // Create a SOCKET
    ListenSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (ListenSocket == INVALID_SOCKET)
    {
        printf("socket failed with error: %d\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }
    printf("Create Socket OK\r\n");

    // Setup the TCP listening socket
    ServerCfg.sin_family = AF_INET;
    ServerCfg.sin_port = htons(DEFAULT_PORT);
    ServerCfg.sin_addr.s_addr = htonl(INADDR_ANY);

    iResult = bind(ListenSocket,(struct sockaddr *)&ServerCfg,
            sizeof(struct sockaddr));
    if(iResult == SOCKET_ERROR)
    {
        printf("bind failed with error: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }   
    printf("Bind to PORT OK\r\n");

    // Begin listen PORT
    iResult = listen(ListenSocket, 5);
    if (iResult == SOCKET_ERROR)
    {
        printf("listen failed with error: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    printf("Start Listen PORT\r\n");
    printf("Waitting Client ...\r\n");

    // Accept a client socket
    ClientSocket = accept(ListenSocket, NULL, NULL);
    if (ClientSocket == INVALID_SOCKET)
    {
        printf("accept failed with error: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    printf("Client Connect Now\r\n");

    // No longer need server socket
    closesocket(ListenSocket);

    // Get Request

    // Receive Full response message

    printf("Receive Web bowser request\r\n");
    memset(RecvBuf, '\0', DEFAULT_BUFLEN);
    iResult = recv(ClientSocket, RecvBuf, DEFAULT_BUFLEN, 0);
    if (iResult < 0)
    {
        printf("receive failed with error: %d\r\n", WSAGetLastError());
    }
    else if(iResult > 0)
    {
        puts(RecvBuf);
    }
    else
    {
        printf("Connect Closed!\r\n");
    }

    // Send html to client
    //printf("Send HTTP Respond:\r\n%s\r\n",RespondInfo);
    iResult = send(ClientSocket, RespondInfo, strlen(RespondInfo), 0);
    if (iResult == SOCKET_ERROR)
    {
        printf("send failed with error: %d\r\n", WSAGetLastError());
    }
    printf("Send OK\r\n");
    //Wait 1S to allow boswer to receive information
    Sleep(1000);
    // shutdown the connection since no more data will be sent
    closesocket(ClientSocket);
    WSACleanup();
    printf("WebServer closed! Press Enter to exit\r\n");
    getch();
}


階段總結





WIFI模塊本身做不了什么,只有和TCP/IP協(xié)議棧,HTTP協(xié)議結合起來(lái),才能發(fā)揮更大的作用。
從分層模型上來(lái)看,WIFI本身僅僅充當物理層和數據鏈路層的作用,因為各層的接口特性,上層只需要關(guān)注下層提供的接口,無(wú)需關(guān)注內部實(shí)現,所以在保證接口不變的前提下,可以直接替換內部模塊。一般開(kāi)發(fā)時(shí),先在PC上調試好應用層代碼,調試ok后,直接將底層代碼替換成WIFI驅動(dòng),這樣就可快速完成模塊。
所以下面的帖子會(huì )先介紹PC上常用的軟件和對應的設置方法,然后用理論加實(shí)踐的方式介紹TCP/IP socket編程入門(mén),HTTP協(xié)議分析和模擬客戶(hù)端,服務(wù)器。








本文地址:http://selenalain.com/thread-103327-1-1.html     【打印本頁(yè)】

本站部分文章為轉載或網(wǎng)友發(fā)布,目的在于傳遞和分享信息,并不代表本網(wǎng)贊同其觀(guān)點(diǎn)和對其真實(shí)性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問(wèn)題,我們將根據著(zhù)作權人的要求,第一時(shí)間更正或刪除。
coocox 發(fā)表于 2012-12-24 09:05:17
                                                                       精簡(jiǎn)版inet_addr

說(shuō)明:
今天在移植代碼的時(shí)候,需要一個(gè)客戶(hù)端WiFiClientConnect函數,該函數的一個(gè)參數為服務(wù)器地址,第二個(gè)為端口。

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

官方的WIFI驅動(dòng)是C++重載函數寫(xiě)的,可以根據不同的輸入格式來(lái)調用對應的函數,C中沒(méi)有重載,只有手工解析,解決方法有3個(gè):

1:分別采用2個(gè)函數,比如提供WiFiClientConnectVia 和Host WiFiClientConnectViaIP兩個(gè)函數,供用戶(hù)調用

2:像Arduino WiFi驅動(dòng)接口那樣,使用一個(gè)函數,但增加一個(gè)入口參數,用于指明服務(wù)器地址類(lèi)型

3:符合Arduino 官方WIFI的調用習慣,用一個(gè)WiFiClientConnect函數,用戶(hù)只需輸入HOST或IP即可,解析的問(wèn)題,交給函數內部來(lái)處理如 WiFiConnect( "www.baidu.com", 80);WiFiConnect( "192.168.2.71", 80)

最終為了方便用戶(hù),采用了最后一個(gè)方案,這樣用戶(hù)可以更加方便的使用WIFI

我們需要在內部識別出是否是有效的IP地址,如果是的話(huà),則轉換為網(wǎng)絡(luò )地址,這樣就需要一個(gè)識別和轉換函數IPToNetAddr。

IPToNetAddr將傳入的IP地址解析成網(wǎng)絡(luò )格式,比如將“192.168.2.71”分割成4個(gè)10進(jìn)制的數字,存到數組里面

在Q群?jiǎn)?wèn)了網(wǎng)友,有人說(shuō)inet_addr符合要求,找到對應源碼后,發(fā)現它考慮的情況太多了,支持各種進(jìn)制的數字,而我們這里,只需要支持10進(jìn)制就ok,網(wǎng)上搜了一下,貌似沒(méi)人寫(xiě)過(guò)這函數,所以還是自己動(dòng)手寫(xiě)一個(gè)吧


要求:

1:能識別出輸入IP字符串是否有效,有效則返回0,無(wú)效則返回-1
2:輸入錯誤的IP地址,函數不損壞存放結果的數組

錯誤的IP例子:
1:子項過(guò)大:每個(gè)子項應小于255。下面的IP地址第一個(gè)子項為1921,大于255
    1921.108.2.71
2:子項過(guò)多:應有4個(gè)子項,由3個(gè).號分隔,下面的IP地址有5個(gè)子項
    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
#include
//#include
#include

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);
}
jlddzeec 發(fā)表于 2018-10-23 09:50:12
學(xué)習學(xué)習!
您需要登錄后才可以發(fā)表評論 登錄 | 立即注冊

相關(guān)視頻

關(guān)于我們  -  服務(wù)條款  -  使用指南  -  站點(diǎn)地圖  -  友情鏈接  -  聯(lián)系我們
電子工程網(wǎng) © 版權所有   京ICP備16069177號 | 京公網(wǎng)安備11010502021702
快速回復 返回頂部 返回列表