重发消息有两个原因:①接收方未收到,此时重发是应该的。②接收方收到消息但是发回的应答包丢失了,此时重发消息则重复了,所以在接收方还得添加一个机制:若收到的消息与以前发过的消息重复,则再次发送应答包。在这些机制下,能够初步的保证UDP传输的完整性。为了UDP包不在IP层上被分片,所以设计UDP包每个不得大于以太网的MTU.采用相互握手重发
直接看代码
public voidrun() {
try{
String local_path = Environment.getExternalStorageDirectory().getPath() +"/gateway_update_file/"+ file_name;
File local_file =new File(local_path);
int size =new Long(local_file.length()).intValue();//文件总的大小
System.out.println("文件总的大小"+" = "+ size);
if(size ==0) {
//当前文件为0,重新获取文件
//........
return;
}
//SEND_SIZE此变量为每包发送的大小(跟接收返回的发送包大小)
PACKETS= (size /SEND_SIZE) +1;//跟接收方定义的接收总的包数(即发送多少包)
InetAddress inetAddress = InetAddress.getByName(GW_IP_ADDRESS);
if(socket==null) {
socket=newDatagramSocket(null);
socket.setReuseAddress(true);
socket.bind(newInetSocketAddress(Constants.UDP_PORT));
socket.setSoTimeout(3000);
}
inti;
int count =1;
FileInputStream fin =new FileInputStream(local_file);
byte[] bytes =new byte[SEND_SIZE];
while((i = fin.read(bytes,0,SEND_SIZE)) != -1) {//循环读取文件
byte[] send_byte = GatewayCmdData.FileDataToGatewayCmd(PACKETS, count, bytes);//此byte数组为与接收方定义的数据结构体
DatagramPacket data =newDatagramPacket(send_byte, send_byte.length, inetAddress, Constants.UDP_PORT);
socket.send(data);
Log.i(TAG+"发送的byte = ", Arrays.toString(bytes));
while(true) {
byte[] rec_byte =new byte[128];
DatagramPacket getack =newDatagramPacket(rec_byte, rec_byte.length);
socket.receive(getack);
if((int) MessageType.A.SEND_UPDATE_FILE_TO_GATEWAY.value() == rec_byte[11]) {过滤掉无用数据
ParseGatewayData.ParseUpdateCountData startUpdateData = new ParseGatewayData.ParseUpdateCountData();
startUpdateData.parseBytes(rec_byte);解析接收到的数据包含发送的数据包次数(即第几包)
if(count == startUpdateData.packet_count) {//如果返回的数据包次数与发送包次数一致,则发送下一包
if(startUpdateData.packet_count==PACKETS) {//最后确认包(即已经完成相关操作)
String crc32 = GatewayInfo.getInstance().getGatewayUpdateCRC32(context);
byte[] bt = GatewayCmdData.FinallyUpdateCmd(crc32);
DatagramPacket packet =newDatagramPacket(bt, bt.length, inetAddress, Constants.UDP_PORT);
socket.send(packet);
Log.i(TAG+" = ", TransformUtils.bytesToHexString(bt));
System.out.println("发送最后一包= "+ TransformUtils.bytesToHexString(bt));
booleanisRun =true;
while(isRun){
socket.receive(getack);
if(rec_byte[32] ==0){
System.out.println("更新成功");
fin.close();
if(socket!=null){
socket.close();
最后关闭socket、文件流
}
isRun =false;
DataSources.getInstance().GatewayUpdateResult(0);
}else{
System.out.println("更新失败");
DataSources.getInstance().GatewayUpdateResult(1);
}
Log.i(TAG,"最后一包返回值= "+ Arrays.toString(rec_byte));
}
}
System.out.println("发送下一包= "+ count);
count++;
break;
}
}else{
Thread.sleep(1000);
System.out.println("未接收到返回重新发送= "+ count);
socket.send(data);
}
}
}
}catch(Exception e) {
e.printStackTrace();
}finally{
System.out.println("finally = "+"UpdateHelper");
}
}