代码改变世界

自动更新功能的实现尝试 之 更新

2004-10-15 23:58  FantasySoft  阅读(1775)  评论(1编辑  收藏

        随着网络的极大发展和普及,很多软件都增加了自动更新的功能,首当其冲的就是Windows了,对于网络游戏的客户端更是必不可少。最近要为一个软件实现自动更新的功能,正好有机会去思考一下这个功能实现起来需要做什么。
        光从字面上看,自动更新至少包含两个方面:一个是更新,一个就是自动了。那么更新的话,我们可以认为是客户端通过HTTP、FTP或者其他连接从服务器上获得需要的资源。在Windows中,有一组API就是应用在这个方面的,这就是WinINet。WinINet有以下几个特殊之处:
        1、HINTERENT:这是在WinINet中使用的Handle,它跟其他的Win32 Handle很类似,其实说到底就是指针了,但是它却不能够跟其他类型的Win32 Handle相互交换使用。而各个函数返回的HINTERNET处于一个树型结构中,其中InternetOpen函数返回的HINTERNET则是这棵树的根结点,也就是调用绝大多数WinINet的API之前,都需要调用InternetOpen函数去进行一些初始化的工作,并且返回一个HINTERNET;
        2、缓存机制:从网络上取得的数据,通常都需要缓存到内存或者硬盘当中,以备后续的程序使用。很多WinINet函数都有支持缓存,我们在使用这些API的时候,都需要去设定缓存标志位来说明采取哪种缓存机制;
        3、错误处理机制:WinINet的错误处理与其他的Win32函数不尽相同,我们可以通过一个WinINet函数的返回值是否为有效的HINTERNET,就可以得知函数调用是否发生错误了。而GetLastError()可以得到更多的错误信息。
        说完了WinINet,回归主题。我们从服务器上获得需要的资源,大致可以遵循这样一个流程:通过InternetOpen函数得到一个HINTERNET handle:handleA;接着基于handleA再利用InterOpenUrl、FtpOpenFile、GopherOpenFile或者HttpOpenRequest函数得到另一个HINTERNET handle:handleB;最后基于handleB利用InternetReadFile函数将所需的文件读到本地的缓冲区,再利用标准的输入流函数将缓冲区的内容写入本地的目标文件。以下是示例代码:

void Update(const char *Url, const char *OutFile)
{

 HINTERNET handleA 
= InternetOpen("Update", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0
);
 
if (handleA !=
 NULL)
 
{
  HINTERNET handleB 
= InternetOpenUrl(handleA, Url, NULL, 0, INTERNET_FLAG_DONT_CACHE, 0
);
  
if (handleB !=
 NULL)
  
{
            
    
byte
 Temp[MAXBLOCKSIZE];
    ULONG Number 
= 1
;

    FILE 
*
stream;
    
if( (stream = fopen( OutFile, "wb" )) !=
 NULL )
    
{
     
while (Number > 0
)
     
{
      InternetReadFile(handleB, Temp, MAXBLOCKSIZE 
- 1&
Number);
      fwrite(Temp, 
sizeof (char
), Number , stream);
     }

     fclose( stream );
    }

   
   InternetCloseHandle(handleB);
   handleB 
= NULL;
  }

  InternetCloseHandle(handleA);
  handleA 
= NULL;
 }

}