本文共 3456 字,大约阅读时间需要 11 分钟。
软件时常需要更新,如果通过在线通知用户肯定会更方便,所以4月底为软件增加了自动检测更新功能,实现原理也很简单,通过获取服务器文件中版本号与软件自身版本号对比,给出提示。下面把实现的代码(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.与远程主机("www.yanxin8.com")建立连接
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.yanxin8.com\r\nConnection: Close\r\n\r\n"; GET这个是表示以什么方式请求,HTTP中还有很多其他的请求方式,常用的GET POST version.txt,要获取的资源的名称,version.txt为网站服务器根目录下的文件 HTTP/1.0表示http协议的版本 Host:www.yanxin8.com,用来指定访问的主机。
1 2 3 4 5 | int nRecv = 0; ///version.txt char *request = "GET /version.txt HTTP/1.0\r\nHost:www.yanxin8.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; |
10.实现效果展示
转载地址:http://tlnws.baihongyu.com/