C++實現軟件自動更新功能

軟件時常需要更新,如果通過在線通知用戶肯定會更方便,實現原理也很簡單,通過獲取服務器文件中版本號與軟件自身版本號對比,給出提示。下面把實現的代碼(C++)貼出來,供大家參考。

0.用到的頭文件

1
2
#include <Shlwapi.h>
#pragma comment(lib, "WS2_32")  // 鏈接到WS2_32.lib

1.啓動Windows Sockets,初始化WS2_32.dll 

1
2
3
4
5
6
7
    WSADATA wsaData;
    WORD sockVersion = MAKEWORD(2, 2);
    if (::WSAStartup(sockVersion, &wsaData) != 0)
    {
        ::WSACleanup();
        return FALSE;
    }

2. 通過"套接字"向網絡發出請求或者應答網絡請求.

1
2
3
4
5
6
7
    SOCKET sClient;
    int ret;
    sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sClient == INVALID_SOCKET)
    {
        return FALSE;
    }

3.設置發送和接收時間爲超時8秒

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    // set Recv and Send time out
    int TimeOut = 8000; // 設置發送超時8秒
    if (setsockopt(sClient, SOL_SOCKET, SO_SNDTIMEO, (char *)&TimeOut, sizeof(TimeOut)) == SOCKET_ERROR)
    {
        closesocket(sClient);
        return FALSE;
    }
 
 
    if (setsockopt(sClient, SOL_SOCKET, SO_RCVTIMEO, (char *)&TimeOut, sizeof(TimeOut)) == SOCKET_ERROR)
    {
        closesocket(sClient);
        return FALSE;
    }

4.獲取與套接口相關的操作參數

1
2
3
4
5
6
7
    unsigned long ul = 1;
    ret = ioctlsocket(sClient, FIONBIO, (unsigned long *)&ul);
    if (ret == SOCKET_ERROR)
    {
        closesocket(sClient);
        return FALSE;
    }

5.sockaddr結構初始化,可通過設置服務器ip或網站地址。
gethostbyname()返回對應於給定主機名的包含主機名字和地址信息的hostent結構指針。結構的聲明與gethostaddr()中一致。
inet_addr(const char* strptr)返回:若字符串有效則將字符串轉換爲32位二進制網絡字節序的IPV4地址,否則爲INADDR_NONE

1
2
3
4
5
6
7
8
9
10
11
12
    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons(80);
    struct hostent *pURL = gethostbyname("www.yanxin8.com");
    //const char* ip = "115.28.9.132";
    //server.sin_addr.s_addr = inet_addr(ip);
    server.sin_addr.s_addr =  *((unsigned long*)pURL->h_addr);
    if (server.sin_addr.s_addr == INADDR_NONE)
    {
        closesocket(sClient);
        return FALSE;
    }

6.與遠程主機建立連接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  BOOL bConnRe = FALSE;
    if (connect(sClient, (struct sockaddr *)&server, sizeof(server)) == -1)
    {
        struct timeval timeout_val;
        fd_set set;
        FD_ZERO(&set);
        FD_SET(sClient, &set);
        timeout_val.tv_sec = 1;
        timeout_val.tv_usec = 0;
        if (select(0, NULL, &set, NULL, &timeout_val) > 0)
        {
            bConnRe = TRUE;
        }
        else
            bConnRe = FALSE;
    }
    else
        bConnRe = TRUE;
 
    if (!bConnRe)
    {
        closesocket(sClient);
        return FALSE;
    }

7.等待接收時間協議返回的時間。學習了Winsock I/O模型之後,最好使用異步I/O,以便設置超時。  
  按照http協議,發送請求數據
  char *request = "GET /version.txt HTTP/1.0\r\nHost:www.xxx.com\r\nConnection: Close\r\n\r\n";
  GET這個是表示以什麼方式請求,HTTP中還有很多其他的請求方式,常用的GET  POST
  version.txt,要獲取的資源的名稱,version.txt爲網站服務器根目錄下的文件
  HTTP/1.0表示http協議的版本
  Host:www.xxx.com,用來指定訪問的主機。

1
2
3
4
5
   int nRecv = 0;
    ///version.txt
    char *request = "GET /version.txt HTTP/1.0\r\nHost:www.xxx.com\r\nConnection: Close\r\n\r\n";
    ret = send(sClient, request, strlen(request), 0);
    Sleep(300);

8.接收返回的數據,然後做解析。下面是返回的數據,可以看到最後一行爲設定的軟件版本。

1
2
3
4
5
6
7
8
9
10
HTTP/1.1 200 OK
Date: Wed, 29 Apr 2015 08:08:02 GMT
Server: Apache/2.4.10 (Unix) OpenSSL/1.0.1e-fips mod_fastcgi/2.4.6
Last-Modified: Tue, 28 Apr 2015 11:04:41 GMT
ETag: "10-514c6d4462440"
Accept-Ranges: bytes
Content-Length: 16
Connection: close
Content-Type: text/plain
noteCard=V1.0.2;
1
2
3
4
5
6
7
8
9
10
11
12
13
  char buf[2000] = { 0 };
    nRecv = ::recv(sClient, buf, 2000, 0);
    if (nRecv > 0){
        string str(buf);
        //strstr(buf, "noteCard=");
        int pos1 = str.find("noteCard=");
        if (pos1 != -1){
            pos1 += 9;
            int pos2 = str.find(";", pos1);
            verstr = str.substr(pos1, pos2 - pos1);
            return true;
        }
    }

9.關閉socket

1
2
3
    closesocket(sClient);
    ::WSACleanup();
     return FALSE;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章