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

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

  AUpdSrvProc.java服务端服务线程,关键代码之一:

 1/** *//********************************************************************
 2 * 项目名称        :rochoc<p>
 3 * 包名称         :com.rochoc.autoupdate<p>
 4 * 文件名称        :AUpdSrvProc.java<p>
 5 * 编写者         :kfzx-luoc<p>
 6 * 编写日期        :2008-12-22<p>
 7 * 程序功能(类)描述  :<p>
 8 * 自动更新服务端处理进程
 9 * 程序变更日期      :
10 * 变更作者        :
11 * 变更说明        :
12********************************************************************/
13package com.rochoc.autoupdate;
14
15import java.io.File;
16import java.io.FileInputStream;
17import java.io.IOException;
18import java.io.InputStream;
19import java.io.OutputStream;
20import java.io.StringReader;
21import java.net.Socket;
22import java.util.HashMap;
23
24/** *//**
25 * @author kfzx-luoc
26 *
27 * TODO To change the template for this generated type comment go to
28 * Window - Preferences - Java - Code Style - Code Templates
29 */
30public class AUpdSrvProc extends Thread
31{
32  private Socket socket = null;
33  private InputStream socketIn;
34  private OutputStream socketOut;  
35  private Config config = Config.getInstance();//配置文件对像
36  private ClientVerParser cvPaser = null;
37  private HashMap cFiles = new HashMap();
38  
39  byte bFlag [] = new byte[1];//标识位
40  byte bCmd[] = new byte[8];//命令
41  
42  public AUpdSrvProc(Socket socket)
43  {
44    this.socket = socket;
45  }  
46  /** *//**
47   * 接收客户端的升级请求,并进行处理
48   */
49  public void run()
50  {
51    try
52    {
53      config.refresh();//重新更新配置信息
54      socketIn = socket.getInputStream();
55      socketOut = socket.getOutputStream();
56      byte datahead [] = new byte[5];//数据头部,第一位用于标识是数据,后四位为长度
57      byte buffer[] = new byte[AUPD.BUFFER_SIZE];//存放数据头部和数据头部
58      byte data[] = new byte[AUPD.DATA_SIZE];//存放具体的数据内容  
59      while(true)
60      {
61        //读取标志位
62        int len = socketIn.read(bFlag,0,1);
63        if(len!=1)
64        {
65          Config.print(socket.getInetAddress()+":读取标识位失败");
66          socketOut.write(Config.getCmd(AUPD.BYE));//结束
67          break;
68        }
69        if(bFlag[0]==AUPD.CMD_DATA_SECT)//命令行
70        {
71          len = socketIn.read(bCmd,0,8);
72          if(len!=8)
73          {
74            Config.print(socket.getInetAddress()+":读取命令失败,CMD="+bCmd);
75            socketOut.write(Config.getCmd(AUPD.BYE));//结束
76            break;
77          }
78          if(Config.parseCmd(bCmd).equals(AUPD.READY_TO_UPDATE))//客户端已经准备好更新了
79          {
80            Config.print(socket.getInetAddress()+":客户端已经准备好接收更新文件");
81            int ret = sendUpdateFile();
82            switch(ret)
83            {
84              case 0:
85                socketOut.write(Config.getCmd(AUPD.UPDATED_FAILURE));//失败
86              break;
87              case 1:
88                socketOut.write(Config.getCmd(AUPD.UPDATED_SUCCESSFUL));//成功
89              break;
90              default:
91                socketOut.write(Config.getCmd(AUPD.NOTNEED_UPDATED));//无需更新
92              break;
93            }
94          }else if(Config.parseCmd(bCmd).equals(AUPD.BYE))//结束链接
95          {
96            socketOut.write(Config.getCmd(AUPD.BYE));//结束
97            break;
98          }
99        }else if(bFlag[0]==AUPD.MARK_DATA_SECT || bFlag[0]==AUPD.MARK_DATA_END)//数据内容
100        {
101          if(Config.parseCmd(bCmd).equals(AUPD.SEND_CLIENT_VERSION))//进行版本信息接收处理
102          {
103            receiveClientVer(bFlag[0]);
104          }else
105          {
106            Config.print("出现非期望数据,"+new String(bCmd));
107            socketOut.write(Config.getCmd(AUPD.BYE));//结束
108            break;
109          }
110        }else
111        {
112          Config.print(socket.getInetAddress()+":非期望标识位,"+bFlag[0]);
113          socketOut.write(Config.getCmd(AUPD.BYE));//结束
114          break;
115        }
116      }//END while(ture)
117      //关闭资源
118      socketIn.close();
119      socketOut.close();
120      socket.close();
121    } catch (IOException e)
122    {
123      Config.print("处理客户端升级请求失败,"+socket.getInetAddress()+","+e);
124      e.printStackTrace();
125    }    
126  }
127  /** *//**
128   * 方法名称:sendUpdateFile<p>
129   * 方法功能:<p>
130   * 参数说明:<p>
131   * 返回:int<p>
132   * 作者:kfzx-luoc
133   * 日期:2008-12-23
134   * @return 0.更新失败 1.更新成功 2.无需更新
135   */
136  private int sendUpdateFile()
137  {
138    try
139    {
140      //检查服务器和客户端版本号是否一致,如果一致辞,则无需升级
141      if (config.getVerstion().equals(cvPaser.getVerstion()))
142      {     
143        Config.print(socket.getInetAddress()+":版本一致,无需更新");        
144        return 2;
145      }
146      //开始进行处理
147      UpdFile srvFiles [] = config.getFiles();
148      boolean isSuccess = true;
149      for(int i=0;i<srvFiles.length;i++)
150      {
151        UpdFile cf = (UpdFile)cFiles.get(srvFiles[i].getName());
152        //文件不存在或版本号不一致则需要更新该文件
153        if(cf==null || !cf.getVersion().equals(srvFiles[i].getVersion()))
154        {
155          if(!sendFile(srvFiles[i]))
156          {
157            isSuccess = false;
158          }          
159        }
160      }//END for
161      //发送版本信息文件,发送更新信息文件
162      if(isSuccess)
163      {
164        UpdFile verFile = new UpdFile("autoupdate.xml");
165        verFile.setPath("." + File.separator + "config");
166        verFile.setType(0);
167        verFile.setVersion(config.getVerstion());
168        if(!sendFile(verFile))
169        {
170          Config.print(socket.getInetAddress()+":发送版本文件失败");
171          return 0;
172        }
173        //发送更新信息
174        UpdFile infFile = new UpdFile("history.htm");
175        infFile.setPath("." + File.separator + "config");
176        infFile.setType(0);
177        infFile.setVersion(config.getVerstion());
178        if(!sendFile(infFile))
179        {
180          Config.print(socket.getInetAddress()+":发送最新信息失败");
181        }
182        return 1;
183      }else
184      {
185        return 0;
186      }
187    }catch(Exception e)
188    {
189      Config.print("处理需要更新文件失败,"+e);
190      e.printStackTrace();
191      return 0;
192    }
193  }
194  //0.失败 1.成功
195  private boolean sendFileAbsPath(String path)
196  {
197    try
198    {
199      byte buffer[] = new byte[AUPD.BUFFER_SIZE];
200      int len = 0;
201      //标识为数据段
202      buffer[0] = AUPD.MARK_DATA_SECT;
203      Config.copyArray(buffer, Config.getLen(path.getBytes().length), 1, 0, 4);//4位长度
204      //组合数据包
205      for (int i = 0; i < path.getBytes().length; i++)
206        buffer[i + 5] = path.getBytes()[i];
207      socketOut.write(buffer, 0, path.getBytes().length + 5);//前五位为头部1位标识+4位长度
208      //标识为数据段已结束,并发送至服务器
209      buffer[0] = AUPD.MARK_DATA_END;
210      socketOut.write(buffer, 0, 1);
211      socketOut.flush();
212      //检查客户端是否收到      
213      len = socketIn.read(bFlag,0,1);
214      if(len!=1)
215      {
216        Config.print(socket.getInetAddress()+":读取标识位失败");
217        socketOut.write(Config.getCmd(AUPD.BYE));//结束
218        return false;
219      }
220      //读取命令
221      len = socketIn.read(bCmd,0,8);
222      if(len!=8)
223      {
224        Config.print(socket.getInetAddress()+":读取命令失败,CMD="+bCmd);
225        socketOut.write(Config.getCmd(AUPD.BYE));//结束
226        return false;
227      }
228      if(Config.parseCmd(bCmd).equals(AUPD.RECEIVED_FILE_ABSOULT))//成功
229      {
230        Config.print(socket.getInetAddress()+":接收文件路径成功,"+path);
231        return true;
232      }else if(Config.parseCmd(bCmd).equals(AUPD.BYE))//失败
233      {
234        Config.print(socket.getInetAddress()+":接收文件路径失败,"+path);
235        return false;
236      }else//异常
237      {
238        return false;
239      }      
240    }catch(Exception e)
241    {
242      Config.print(socket.getInetAddress()+":发送文件路径失败,"+path);
243      e.printStackTrace();
244      return false;
245    }
246  }
247  //false.失败 true.成功
248  private boolean sendFile(UpdFile file)
249  {
250    try
251    {
252      File f = new File(Config.formatPath(file.getPath())+file.getName());
253      if(!f.exists()||!f.isFile())
254      {
255        Config.print(file+",不存在,无法更新");
256        return false;
257      }
258      Config.print(socket.getInetAddress()+":开始传输文件>>"+file);
259      socketOut.write(Config.getCmd(AUPD.SEND_FILE_ABSOULT));//发送文件全路径
260      String fileAbsPath = Config.formatPath(file.getPath())+file.getName();
261      if(!sendFileAbsPath(fileAbsPath))
262      {
263        return false;
264      }
265      socketOut.write(Config.getCmd(AUPD.START_TRANSMIT));//开始传输
266      FileInputStream fin = new FileInputStream(f);
267      //文件数据缓冲区
268      byte[] data = new byte[AUPD.DATA_SIZE];
269      // 发送数据缓冲区
270      byte[] buffer = new byte[AUPD.BUFFER_SIZE];
271      int len = -1;
272      while ((len=fin.read(data)) != -1)
273      {
274        // 标识为数据段
275        buffer[0] = AUPD.MARK_DATA_SECT;
276        Config.copyArray(buffer,Config.getLen(len),1,0,4);//存放长度
277        // 组合数据包
278        for (int i=0; i<len; i++)
279          buffer[i+5] = data[i];
280        socketOut.write(buffer,0,len+5);
281      }
282      // 标识为数据段已结束,并发送至服务器
283      buffer[0] = AUPD.MARK_DATA_END;      
284      socketOut.write(buffer,0,1);
285      socketOut.flush();
286      fin.close();
287      //判断客户端是否收到
288      len = socketIn.read(bFlag,0,1);
289      if(len!=1)
290      {
291        Config.print(socket.getInetAddress()+":读取标识位失败");
292        socketOut.write(Config.getCmd(AUPD.BYE));//结束
293        return false;
294      }
295      //读取命令
296      len = socketIn.read(bCmd,0,8);
297      if(len!=8)
298      {
299        Config.print(socket.getInetAddress()+":读取命令失败,CMD="+new String(bCmd));
300        socketOut.write(Config.getCmd(AUPD.BYE));//结束
301        return false;
302      }
303      if(Config.parseCmd(bCmd).equals(AUPD.TERMINATE_TRANSMIT))//成功
304      {
305        Config.print(socket.getInetAddress()+":传输文件'"+file+"'成功");
306        return true;
307      }else if(Config.parseCmd(bCmd).equals(AUPD.BYE))//失败
308      {
309        Config.print(socket.getInetAddress()+":传输文件失败,"+file);
310        return false;
311      }else//异常
312      {
313        Config.print(socket.getInetAddress()+":传输文件异常,"+file+","+new String(bCmd));
314        return false;
315      }
316    }catch(Exception e)
317    {
318      Config.print("传输文件'"+file+"'失败,"+e);
319      e.printStackTrace();
320      return false;
321    }
322  }
323  private void receiveClientVer(byte flag)//第一位表示是数据内容还是结束内容
324  {
325    try
326    {
327      //接收数据缓冲区
328      byte flagb[] = new byte[1];//标志
329      byte lenb [] = new byte[4];//长度
330      //接收版本号信息
331      StringBuffer strBuf = new StringBuffer();//用于接收信息
332      int len = -1;
333      boolean isFirst = true;
334      boolean isOk = false;    
335      flagb[0] = flag;
336      while(true)
337      {
338        //第一次
339        if(isFirst)
340        {
341          isFirst = false;    
342        }else
343        {
344          len = socketIn.read(flagb,0,1);//读取标识位
345          if(len != 1)
346          {
347            Config.print(socket.getInetAddress() + ":读取数据标识位失败");
348            break;
349          }
350        }
351        //读取数据长度
352        if(flagb[0]==AUPD.MARK_DATA_SECT)
353        {
354          len = socketIn.read(lenb, 0, 4);
355          if (len != 4)
356          {
357            Config.print(socket.getInetAddress() + ":读取数据头部失败");
358            break;
359          }
360        }
361        if (flagb[0] == AUPD.MARK_DATA_SECT)//数据内容
362        {
363          int cLen = Integer.parseInt(new String(lenb, 0, 4));//数据内容长度
364          byte data[] = new byte[cLen];
365          len = socketIn.read(data, 0, cLen);
366          int totLen = len;
367          while (totLen < cLen)//不足位要重重读取
368          {
369            strBuf.append(new String(data, 0, len));
370            len = socketIn.read(data, 0, cLen - totLen);
371            totLen = totLen + len;
372          }
373          strBuf.append(new String(data, 0, len));
374        }else if(flagb[0]==AUPD.MARK_DATA_END)//数据结束
375        {
376          isOk = true;
377          break;
378        }else
379        {
380          Config.print(socket.getInetAddress()+":收到非期望数据,"+new String(flagb,0,1)+"<<");
381          break;
382        }
383      }//END while(true)
384      if(isOk)//成功
385      {
386        socketOut.write(Config.getCmd(AUPD.RECEIVED_CLIENT_VERSION));//临时测试
387        Config.print("接收客户端" + socket.getInetAddress() + " 版本信息成功");
388        cvPaser = new ClientVerParser(new StringReader(strBuf
389            .toString()));
390        UpdFile files[] = cvPaser.getFiles();
391        for (int i = 0; i < files.length; i++)
392        {
393          cFiles.put(files[i].getName(), files[i]);
394        }
395      }else//失败
396      {
397        socketOut.write(Config.getCmd(AUPD.BYE));//结束
398      }
399    }catch(Exception e)
400    {
401      Config.print("接收客户端"+socket.getInetAddress()+" 版本号信息处理失败,"+e);
402    }
403  }  
404}