C++实现软件自动更新功能

软件时常需要更新,如果通过在线通知用户肯定会更方便,实现原理也很简单,通过获取服务器文件中版本号与软件自身版本号对比,给出提示。下面把实现的代码(C++)贴出来,供大家参考。

0.用到的头文件

1
2
#include 
#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;

你可能感兴趣的:(Qt-网络编程)