CS结构软件自动升级实现(三)
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}