CS结构软件自动升级实现(四)

来源:岁月联盟 编辑:zhuzhu 时间:2009-01-18

  ClientVerParser.java:

1/** *//********************************************************************
2 * 项目名称        :rochoc<p>
3 * 包名称         :com.rochoc.autoupdate<p>
4 * 文件名称        :ClientVerParser.java<p>
5 * 编写者         :kfzx-luoc<p>
6 * 编写日期        :2008-12-23<p>
7 * 程序功能(类)描述  :<p>
8 * 客户端版本号解释器
9 * 程序变更日期      :
10 * 变更作者        :
11 * 变更说明        :
12********************************************************************/
13package com.rochoc.autoupdate;
14
15import java.io.Reader;
16import java.util.List;
17
18import org.dom4j.Document;
19import org.dom4j.Element;
20import org.dom4j.io.SAXReader;
21
22/** *//**
23 * @author kfzx-luoc
24 *
25 * TODO To change the template for this generated type comment go to
26 * Window - Preferences - Java - Code Style - Code Templates
27 */
28public class ClientVerParser
29{
30  private Reader xml = null;
31  /** *//** xml的document*/
32  private Document doc = null;
33  
34  public ClientVerParser(Reader reader)
35  {
36    xml = reader;
37    parse();
38  }
39  
40  private void parse()
41  {
42    try
43    {
44      SAXReader reader = new SAXReader();
45      doc = reader.read(xml);
46    }catch(Exception e)
47    {
48      e.printStackTrace();
49    }
50  }
51  public String getVerstion()
52  {
53    List lst = doc.selectNodes("Info/Version");
54    Element el = (Element)lst.get(0);
55    return el.getText();
56  }
57  public UpdFile [] getFiles()
58  {
59    List file = doc.selectNodes("Info/Files");
60    List lst = ((Element)file.get(0)).elements();
61    if(lst.size()==0)
62    {
63      return null;
64    }
65    UpdFile files[] = new UpdFile[lst.size()];
66    for(int i=0;i<lst.size();i++)
67    {
68      Element el = (Element)lst.get(i);
69      List childs = el.elements();
70      Element name = (Element)childs.get(0);//Name
71      Element path = (Element)childs.get(1);//Path
72      Element ver = (Element)childs.get(2);//Version
73      files[i] = new UpdFile(name.getText());
74      if("File".equals(el.getName()))
75      {
76        files[i].setType(0);//文件
77      }else
78      {
79        files[i].setType(1);//目录
80      }
81      files[i].setPath(path.getText());
82      files[i].setVersion(ver.getText());
83    }
84    return files;
85  }
86  public String getServerPort()
87  {
88    List lst = doc.selectNodes("Info/UpdateServer/Port");
89    Element el = (Element)lst.get(0);
90    return el.getText();
91  }
92}
AutoUpdateClient.java客户端升级处理进程,关键代码之二: 1/** *//********************************************************************
 2 * 项目名称        :rochoc<p>
 3 * 包名称         :com.rochoc.autoupdate<p>
 4 * 文件名称        :AutoUpdateClient.java<p>
 5 * 编写者         :kfzx-luoc<p>
 6 * 编写日期        :2008-12-23<p>
 7 * 程序功能(类)描述  :<p>
 8 * 自动升级客户端对像
 9 * 程序变更日期      :
10 * 变更作者        :
11 * 变更说明        :
12********************************************************************/
13package com.rochoc.autoupdate;
14
15import java.io.File;
16import java.io.FileInputStream;
17import java.io.FileOutputStream;
18import java.io.InputStream;
19import java.io.OutputStream;
20import java.net.Socket;
21
22/** *//**
23 * @author kfzx-luoc
24 *
25 * TODO To change the template for this generated type comment go to
26 * Window - Preferences - Java - Code Style - Code Templates
27 */
28public class AutoUpdateClient
29{
30  private Socket socket = null;
31  private OutputStream socketOut;
32  private InputStream socketIn;
33  private Config config = Config.getInstance();//配置文件对像
34  private String currFileAbs = "";//当前更新文件的全路径
35  public AutoUpdateClient()
36  {
37    try
38    {
39      socket = new Socket(config.getServerIp(),Integer.parseInt(config.getServerPort()));
40      socket.setSoTimeout(30000);//30秒
41    }catch(Exception e)
42    {
43      Config.print("创建与自动升级服务器之间的连接失败,"+e);
44      e.printStackTrace();
45    }
46  }
47  public void update()
48  {
49    if(socket == null)
50    {
51      Config.print("无法与服务器连接,升级失败");
52      return;
53    }
54    try
55    {
56      socketOut = socket.getOutputStream();
57      socketIn = socket.getInputStream();   
58      
59      //开始升级处理
60      byte flag [] = new byte[1];
61      byte cmd[] = new byte[8];//命令
62      byte datahead [] = new byte[5];//数据头部,第一位用于标识是数据,后四位为长度
63      byte buffer[] = new byte[AUPD.BUFFER_SIZE];//存放数据头部和数据头部
64      byte data[] = new byte[AUPD.DATA_SIZE];//存放具体的数据内容      
65      //发送本地版本信息给服务器        
66      socketOut.write(Config.getCmd(AUPD.SEND_CLIENT_VERSION));//发送传输版本信息命令
67      sendClientVer();//发送版本信息
68      while(true)
69      {
70        //读取信息
71        int len = socketIn.read(flag,0,1);
72        if(len!=1)
73        {
74          Config.print("读取标识位失败");
75          socketOut.write(Config.getCmd(AUPD.BYE));//结束
76          break;
77        }
78        if(flag[0]==AUPD.CMD_DATA_SECT)//命令行
79        {
80          len = socketIn.read(cmd,0,8);
81          if(len!=8)
82          {
83            Config.print("读取命令失败");
84            socketOut.write(Config.getCmd(AUPD.BYE));//结束
85            break;
86          }
87          if(Config.parseCmd(cmd).equals(AUPD.RECEIVED_CLIENT_VERSION))//收到版本信息
88          {
89            Config.print("服务器成功收到版本信息");
90            socketOut.write(Config.getCmd(AUPD.READY_TO_UPDATE));
91            continue;
92          }else if(Config.parseCmd(cmd).equals(AUPD.SEND_FILE_ABSOULT))//接收文件全路径
93          {
94            Config.print("开始接收文件路径名");            
95          }else if(Config.parseCmd(cmd).equals(AUPD.UPDATED_FAILURE))//更新失败
96          {
97            Config.print("版本更新失败");
98            socketOut.write(Config.getCmd(AUPD.BYE));//结束
99            break;
100          }else if(Config.parseCmd(cmd).equals(AUPD.UPDATED_SUCCESSFUL))//更新成功
101          {
102            Config.print("版本更新成功");
103            socketOut.write(Config.getCmd(AUPD.BYE));//结束
104            //打开最新信息
105            openFile(".confighistory.htm");
106            break;
107          }else if(Config.parseCmd(cmd).equals(AUPD.NOTNEED_UPDATED))//无需更新
108          {
109            Config.print("已经是最新版本,无需更新");
110            socketOut.write(Config.getCmd(AUPD.BYE));//结束
111            break;
112          }else if(Config.parseCmd(cmd).equals(AUPD.BYE))//结束链接
113          {
114            socketOut.write(Config.getCmd(AUPD.BYE));//结束
115            break;
116          }
117        }else if(flag[0]==AUPD.MARK_DATA_SECT || flag[0]==AUPD.MARK_DATA_END)//数据内容
118        {
119          if(Config.parseCmd(cmd).equals(AUPD.SEND_FILE_ABSOULT))//接收文件全路径
120          {
121            currFileAbs = receiveFileAbsPath(flag[0]);
122            if(currFileAbs!=null && !currFileAbs.equals(""))//成功
123            {
124              socketOut.write(Config.getCmd(AUPD.RECEIVED_FILE_ABSOULT));
125              Config.print("接收文件全路径‘"+currFileAbs+"’成功");
126            }else
127            {
128              Config.print("接收文件全路径失败");
129              socketOut.write(Config.getCmd(AUPD.BYE));//结束
130              break;
131            }
132          }else if(Config.parseCmd(cmd).equals(AUPD.START_TRANSMIT))//接收文件
133          {
134            if(receiveFile(flag[0]))
135            {
136              socketOut.write(Config.getCmd(AUPD.TERMINATE_TRANSMIT));
137            }else
138            {
139              socketOut.write(Config.getCmd(AUPD.BYE));
140            }
141          }else
142          {
143            Config.print("出现非期望数据,"+new String(cmd));
144            socketOut.write(Config.getCmd(AUPD.BYE));//结束
145            break;
146          }
147        }else
148        {
149          Config.print("非期望标识位,"+flag[0]);
150          socketOut.write(Config.getCmd(AUPD.BYE));//结束
151          break;
152        }
153      }//END while(true)
154      
155      //关闭资源及链接
156      socketOut.close();
157      socketIn.close();
158      socket.close();
159      Config.print("自动升级处理完毕");
160    }catch(Exception e)
161    {
162      Config.print("升级处理失败,"+e);
163      e.printStackTrace();
164    }
165  }
166  private void openFile(String file)
167  {
168    try
169    {
170      Runtime.getRuntime().exec("cmd /c "+file);
171    }catch(Exception e)
172    {
173      e.printStackTrace();
174    }
175  }
176  private String receiveFileAbsPath(byte flag)
177  {
178    String absPath = "";
179    //接收文件全路径
180    try
181    {
182      //接收数据缓冲区
183      byte flagb[] = new byte[1];//标志
184      byte lenb [] = new byte[4];//长度
185      //接收文件全路径
186      StringBuffer strBuf = new StringBuffer();//用于接收信息
187      int len = -1;
188      boolean isFirst = true;
189      boolean isOk = false;    
190      flagb[0] = flag;
191      while(true)
192      {
193        //第一次
194        if(isFirst)
195        {
196          isFirst = false;    
197        }else
198        {
199          len = socketIn.read(flagb,0,1);//读取标识位
200          if(len != 1)
201          {
202            Config.print(socket.getInetAddress() + ":读取数据标识位失败");
203            break;
204          }
205        }
206        //读取数据长度
207        if(flagb[0]==AUPD.MARK_DATA_SECT)
208        {
209          len = socketIn.read(lenb, 0, 4);
210          if (len != 4)
211          {
212            Config.print(socket.getInetAddress() + ":读取数据头部失败");
213            break;
214          }
215        }
216        if (flagb[0] == AUPD.MARK_DATA_SECT)//数据内容
217        {
218          int cLen = Integer.parseInt(new String(lenb, 0, 4));//数据内容长度
219          byte data[] = new byte[cLen];
220          len = socketIn.read(data, 0, cLen);
221          System.out.println("len:"+len+"cLen="+cLen+">>"+new String(data,0,len));
222          int totLen = len;
223          while (totLen < cLen)//不足位要重重读取
224          {
225            strBuf.append(new String(data, 0, len));
226            len = socketIn.read(data, 0, cLen - totLen);
227            totLen = totLen + len;
228            System.out.println("len:"+len+"cLen="+cLen);
229          }
230          strBuf.append(new String(data, 0, len));
231        }else if(flagb[0]==AUPD.MARK_DATA_END)//数据结束
232        {
233          isOk = true;
234          break;
235        }else
236        {
237          Config.print(socket.getInetAddress()+":收到非期望数据,"+new String(flagb,0,1)+"<<");
238          break;
239        }
240      }//END while(true)
241      if(isOk)//成功
242      {      
243        absPath = strBuf.toString();
244      }else//失败
245      {
246        socketOut.write(Config.getCmd(AUPD.BYE));//结束
247      }
248    }catch(Exception e)
249    {
250      Config.print("接收文件全路径处理失败,"+e);
251    }
252    return absPath;
253  }
254  private boolean receiveFile(byte flag)
255  {
256    try
257    {
258      if(currFileAbs==null||currFileAbs.equals(""))
259      {
260        Config.print("无法获取更新文件信息,更新失败");
261        return false;
262      }
263      File file;
264      //先检查目录是否存在
265      //得到目录
266      int idx = currFileAbs.lastIndexOf(File.separator);
267      String path = currFileAbs.substring(0,idx);
268      file = new File(path);
269      if(!file.isDirectory() || !file.exists())
270      {
271        Config.print("新创建目录:"+path);
272        file.mkdir();
273      }
274      file = new File(currFileAbs);
275      FileOutputStream fout = new FileOutputStream(file);
276      //接收数据缓冲区
277      byte flagb[] = new byte[1];//标志
278      byte lenb [] = new byte[4];//长度
279      int len = -1;
280      boolean isFirst = true;
281      boolean isOk = false;
282      flagb[0] = flag;
283      //接收上传的文件数据
284      while (true)
285      {
286        //第一次
287        if(isFirst)
288        {
289          isFirst = false;    
290        }else
291        {
292          len = socketIn.read(flagb,0,1);//读取标识位
293          if(len != 1)
294          {
295            Config.print(socket.getInetAddress() + ":读取数据标识位失败");
296            break;
297          }
298        }
299        //读取数据长度
300        if(flagb[0]==AUPD.MARK_DATA_SECT)
301        {
302          len = socketIn.read(lenb, 0, 4);
303          if (len != 4)
304          {
305            Config.print(socket.getInetAddress() + ":读取数据头部失败");
306            break;
307          }
308        }
309        if (flagb[0] == AUPD.MARK_DATA_SECT)//数据内容
310        {
311          int cLen = Integer.parseInt(new String(lenb, 0, 4));//数据内容长度
312          byte data[] = new byte[cLen];
313          len = socketIn.read(data, 0, cLen);
314          int totLen = len;
315          while (totLen < cLen)//不足位要重重读取
316          {
317            fout.write(data,0,len);
318            len = socketIn.read(data, 0, cLen - totLen);
319            totLen = totLen + len;
320          }
321          fout.write(data,0,len);
322        }else if(flagb[0]==AUPD.MARK_DATA_END)//数据结束
323        {
324          isOk = true;
325          break;
326        }else
327        {
328          Config.print(socket.getInetAddress()+":收到非期望数据,"+new String(flagb,0,1)+"<<");
329          break;
330        }
331      }//END while
332      fout.flush();
333      fout.close();
334      if(isOk)
335      {
336        Config.print("成功更新文件:"+file.getAbsolutePath());
337        return true;
338      }else
339      {
340        Config.print("更新文件:"+file.getAbsolutePath()+"失败");        
341        return false;
342      }
343    }catch(Exception e)
344    {
345      Config.print("下载更新文件'"+currFileAbs+"'失败,"+e);
346      e.printStackTrace();
347      return false;
348    }
349  }
350  //发送客户端版本信息
351  private void sendClientVer()
352  {
353    try
354    {
355      File verFile = new File(Config.cfgFile);
356      if(!verFile.isFile() || !verFile.exists())
357      {
358        Config.print("版本信息文件不存在");
359        return;
360      }
361      //开始发送
362      FileInputStream fis = new FileInputStream(verFile);
363      byte buffer[] = new byte[AUPD.BUFFER_SIZE];
364      byte data[] = new byte[AUPD.DATA_SIZE];
365      int len = 0;
366      while((len=fis.read(data))!=-1)
367      {
368        //标识为数据段
369        buffer[0] = AUPD.MARK_DATA_SECT;
370        Config.copyArray(buffer,Config.getLen(len),1,0,4);//4位长度
371        //组合数据包
372        for (int i=0; i<len; i++)
373          buffer[i+5] = data[i];//前五位为头部1位标识+4位长度
374        socketOut.write(buffer,0,len+5);//发送数据
375      }//END while
376      //标识为数据段已结束,并发送至服务器
377      buffer[0] = AUPD.MARK_DATA_END;
378      socketOut.write(buffer,0,1);
379      socketOut.flush();
380      fis.close();
381      Config.print("版本信息传送完毕");
382    }catch(Exception e)
383    {
384      Config.print("发送版本信息给服务器失败,"+e);
385      e.printStackTrace();
386    }
387  }  
388  //测试主流程
389  public static void main(String args[])
390  {
391    AutoUpdateClient client = new AutoUpdateClient();
392    client.update();
393  }
394}
看来源码还是有点多,只能再分一次了,否则电脑就快死机了,