/*接收开始传输包*/ public int ReceiveStart() { //DatagramPacket sendPacket = null, receivePacket = null; //用于发送开始确认包 byte[] sendBuffer = new byte[StartAckTip[0]]; //用于接收开始传输包 byte[] receiveBuffer = new byte[FilePropertyTip[0]]; try { udpReceiveClient.Client.ReceiveTimeout = 0; } catch (Exception e) { log.Error("ReceiveStart", e); } while (true) { try { //socket.receive(receivePacket); receiveBuffer = udpReceiveClient.Receive(ref host); receiveState.AddHaveReceiveBytes(receiveBuffer.Length); //检查标识 String str = Encoding.Default.GetString(receiveBuffer, StartTip[1], 4); if (!datagramStart.Equals(str)) { continue; } //获取次随机数 int numberRandom = ByteChange.ByteToInt(receiveBuffer, StartTip[2]); SendStartAck(numberRandom); // System.out.println("接收到开始传输包"); return(numberRandom); } catch (Exception ex) { // Logger.getLogger(ReceiveLittle.class.getName()).log(Level.SEVERE, null, ex); //logger.error("{}", ex); //MessageBox.Show(ex.ToString()); log.Error(ex.ToString()); } } }
/* 发送结束传输包 */ public void SendOver(int numberRandom) { // 设定接收超时1ms udpSendClient.Client.ReceiveTimeout = sendState.WaitTime; // 生成传输结束包 //DatagramPacket packetOver, packetOverAck; byte[] overBuffer = new byte[StopTip[0]]; byte[] overAckBuffer = new byte[StopAckTip[0]]; // 填充标识 ByteChange.StringToByte(datagramStop, overBuffer, StopTip[1], datagramStop.Length); // 填充次随机数 ByteChange.IntToByte(overBuffer, StopTip[2], numberRandom); // 填充报尾 ByteChange.StringToByte(datagramTail, overBuffer, StopTip[3], datagramTail.Length); try { while (true) { try { udpSendClient.Send(overBuffer, overBuffer.Length, host); // sendState.addHaveSendBytes(packetOver.getLength()); sendState.AddNumHaveSendBytes(overAckBuffer.Length); ByteChange.CleanByte(overAckBuffer); overAckBuffer = udpSendClient.Receive(ref host); // 检查ACK标识 String str = Encoding.Default.GetString(overAckBuffer, StopAckTip[1], 4); if (!datagramStopAck.Equals(str)) { continue; } // 检查次随机数 int num = ByteChange.ByteToInt(overAckBuffer, StopAckTip[2]); if (num != numberRandom) { continue; } break; } catch (SocketException ex) { if (ex.ErrorCode == 10060) { continue; } //MessageBox.Show(ex.ToString()); //if (ex is TimeoutException) //{ // continue; // // 接收超时,则继续循环 //} //if(ex is SocketException) //{ // continue; //} } } } catch (Exception ex) { //logger.error("{}", ex); log.Error(ex.ToString()); } }
/* 接收请求重发包 */ /* 返回接收方是否接收完毕 */ public bool GetDatagramReq(int numberRandom, int blockRandom, int littleRandom, bool[] sendTip) { //log.Info("GetDatagramReq进入"); // 首先,设置接收超时5ms //DatagramPacket packetReq = null; // 由于请求重发包发送的是需要重发的分组 // 所以,先将成功发送标记全部置true,再根据 for (int i = 0; i < sendTip.Length; i++) { sendTip[i] = true; } // 请求重发包将发送失败的置false byte[] buffer = new byte[ReqAgainTip[0]]; bool canSendFinish = true; while (true) { try { if (canSendFinish) { udpSendClient.Client.ReceiveTimeout = sendState.WaitTime; SendFinish(numberRandom, blockRandom, littleRandom); } ByteChange.CleanByte(buffer); buffer = udpSendClient.Receive(ref host); // 如果接收到数据包,不管是否正确,下一轮都不能发未接收请求重发包 canSendFinish = false; // 对接收到的请法求重发包进行解析 // 检证是不是请求重发包 String s = Encoding.Default.GetString(buffer, ReqAgainTip[1], 4); if (!datagramReqAgain.Equals(s)) { continue; } // 匹配次随机数 int r = ByteChange.ByteToInt(buffer, ReqAgainTip[2]); if (r != numberRandom) { continue; } // 匹配块随机数 r = ByteChange.ByteToInt(buffer, ReqAgainTip[3]); if (r != blockRandom) { continue; } // //验证该包是否完整 // s=new String(buffer,1014,4); // if(!s.equals(datagramTail)){ // continue; // } // 验证此请求重发包的小随机数是否与本次发送的"发送完毕包"相同 r = ByteChange.ByteToInt(buffer, ReqAgainTip[4]); if (r != littleRandom) { continue; } // 验证完毕,提取请求重发的分组 // 提取数据长度 int length = ByteChange.ByteToShort(buffer, ReqAgainTip[5]); // 如果数据长度是0,验证一下数据完整性,如果完整,则返回数据接收完毕 if (length == 0) { //s = new String(buffer, ReqAgainTip[5] + 2, 4); s = Encoding.Default.GetString(buffer, ReqAgainTip[5] + 2, 4); //if (s.equals(datagramTail)) if (datagramTail.Equals(s)) { // 数据完整,返回 //log.Info("GetDatagramReq退出true"); return(true); } else { // 数据不完整,此包无效,继续循环 continue; } } else { sendState.NumResendPackets = 0; for (int i = 0; i < length; i++) { int tip = ByteChange.ByteToShort(buffer, i * 2 + ReqAgainTip[6]); sendTip[tip] = false; sendState.AddNumResendPackets(); } //log.Info("GetDatagramReq退出"); break; } } catch (SocketException ex) { // Logger.getLogger(Send.class.getName()).log(Level.SEVERE,null, ex); // 如果是接收超时,那么下一次循环就应该发送"发送完毕包" if (ex.ErrorCode == 10060) { canSendFinish = true; int time = sendState.WaitTime; if (time <= 1800 && time > 0) { sendState.WaitTime = (time + 10);//延迟时间+10 } } } } return(false); }
/* 发送分组头 */ public void SendDatagramHead(int numberRandom, int blockRandom, int number) { //log.Info("SendDatagramHead进入"); byte[] buffer = new byte[HeadTip[0]]; // 填充分组头标识 ByteChange.StringToByte(datagramHead, buffer, HeadTip[1], 4); // 填充次随机数 ByteChange.IntToByte(buffer, HeadTip[2], numberRandom); // 填充块随机数 ByteChange.IntToByte(buffer, HeadTip[3], blockRandom); // 写入数组数量 //assert number <= groupNum : "分组数量超过500"; if (number > groupNum) { throw new Exception("分组数量超过500"); } ByteChange.ShortToByte(buffer, HeadTip[4], (short)number); // 填充报尾标识 ByteChange.StringToByte(datagramTail, buffer, HeadTip[5], 4); // 发送分组头 // 发送后接收报头确认报,接收超时或者接收的不匹配则重发分组头 bool canSendHead = true; while (true) { try { if (canSendHead) { udpSendClient.Client.ReceiveTimeout = sendState.WaitTime; udpSendClient.Send(buffer, buffer.Length, host); sendState.AddNumHaveSendBytes(buffer.Length); } byte[] c = new byte[HeadAckTip[0]]; ByteChange.CleanByte(c); c = udpSendClient.Receive(ref host); // 只要接收到数据包,不论是不正确,下次循环就不能发送头 canSendHead = false; // 进行检查 // 1.检查其是否是分组头确认包 //String s = new String(c, HeadAckTip[1], 4); String s = Encoding.Default.GetString(c, HeadAckTip[1], 4); //if (!s.equals(datagramHeadAck)) if (!datagramHeadAck.Equals(s)) { continue; } // 2.检查其次随机数,是否与自己的匹配 int r = ByteChange.ByteToInt(c, HeadAckTip[2]); if (r != numberRandom) { continue; } // 3.检查其块随机数 r = ByteChange.ByteToInt(c, HeadAckTip[3]); if (r != blockRandom) { continue; } // 所有检查均正确,发送成功,返回 int time = sendState.WaitTime; if (time <= 2000 && time >= 4) { sendState.WaitTime = (time / 2);//延迟时间翻倍 } //logger.info("WaitTime={}",sendState.getWaitTime()); //log.Info("SendDatagramHead退出"); break; } catch (SocketException ex) { //MessageBox.Show(ex.ToString()); // Logger.getLogger(Send.class.getName()).log(Level.SEVERE, // null, ex); // 如果是接收超时,则一下次循环的时候,要先发送头 if (ex.ErrorCode == 10060) { canSendHead = true; int time = sendState.WaitTime; if (time <= 1800 && time > 0) { sendState.WaitTime = (time + 10);//延迟时间+10 } // logger.info("WaitTime={}",sendState.getWaitTime()); } //if (ex is TimeoutException) //{ // canSendHead = true; //} //if(ex is SocketException) //{ // canSendHead = true; //} //canSendHead = true; } } }
/* 发送开始传输包 */ public void SendStart(int numberRandom) { //log.Info("SendStart进入"); byte[] sendBuffer = new byte[StartTip[0]]; byte[] receiveBuffer = new byte[StartAckTip[0]]; // 填充开始传输包 ByteChange.StringToByte(datagramStart, sendBuffer, StartTip[1], 4); ByteChange.IntToByte(sendBuffer, StartTip[2], numberRandom); ByteChange.StringToByte(datagramTail, sendBuffer, StartTip[3], 4); // 设置超时1ms及初始化数据包 bool canSend = true; while (true) { try { if (canSend) { udpSendClient.Client.ReceiveTimeout = sendState.WaitTime; udpSendClient.Send(sendBuffer, sendBuffer.Length, host); sendState.AddNumHaveSendBytes(sendBuffer.Length); } receiveBuffer = udpSendClient.Receive(ref host); // 如果接收到数据包,无论如何,下一次都不能发送 canSend = false; // 判断标识 String str = Encoding.Default.GetString(receiveBuffer, StartAckTip[1], 4); if (!datagramStartAck.Equals(str)) { continue; } // 判断次随机数 int num = ByteChange.ByteToInt(receiveBuffer, StartAckTip[2]); if (num != numberRandom) { continue; } // 否则接收成功,退出循环 int time = sendState.WaitTime; if (time <= 2000 && time >= 4) { sendState.WaitTime = time / 2;//延迟时间减半 } // logger.info("WaitTime={}",sendState.getWaitTime()); //log.Info("SendStart退出"); break; } catch (SocketException e) { if (e.ErrorCode == 10060) { canSend = true; int time = sendState.WaitTime; if (time <= 1800 && time > 0) { sendState.WaitTime = (time + 10);//延迟时间+10 } } //MessageBox.Show(e.ToString()); //if (e is TimeoutException) //{ // canSend = true; // //int time = sendState.getWaitTime(); // //if (time <= 1800 && time > 0) // //{ // // sendState.setWaitTime(time + 10);//延迟时间+10 // //} // // logger.info("WaitTime={}",sendState.getWaitTime()); //} //if(e is SocketException) //{ //} } } // System.out.println("开始发送包发送完毕退出"); }
/*发送传输结束确认包*/ public void SendOverAck(int numberRandom) { //DatagramPacket packetOverAck = null, packetOver = null; byte[] sendBuffer = new byte[StopAckTip[0]]; byte[] receiveBuffer = new byte[StopTip[0]]; //设置接收超时1000ms try { //socket.setSoTimeout(1000); udpReceiveClient.Client.ReceiveTimeout = 1000; /*填充结束确认包*/ //填充确认包标识 ByteChange.StringToByte(datagramStopAck, sendBuffer, StopAckTip[1], 4); //填充次随机数 ByteChange.IntToByte(sendBuffer, StopAckTip[2], numberRandom); //填充报尾 ByteChange.StringToByte(datagramTail, sendBuffer, StopAckTip[3], 4); /*填充完毕*/ //packetOverAck = new DatagramPacket(sendBuffer, sendBuffer.length, InetAddress.getByName(yourAddress), yourPort); //packetOver = new DatagramPacket(receiveBuffer, receiveBuffer.length); } catch (Exception ex) { log.Error(ex.ToString()); // Logger.getLogger(ReceiveLittle.class.getName()).log(Level.SEVERE, null, ex); //logger.error("{}", ex); } bool canSendAck = true; while (true) { try { if (canSendAck) { //socket.send(packetOverAck); udpReceiveClient.Send(sendBuffer, sendBuffer.Length, host); } ByteChange.CleanByte(receiveBuffer); //socket.receive(packetOver); receiveBuffer = udpReceiveClient.Receive(ref host); //receiveState.addHaveReceiveBytes(packetOver.getLength()); // System.out.println("Over:收到包,IP"+packetOver.getAddress()); //如果接收到传输结束包,就继续循环 //String str = new String(receiveBuffer, StopTip[1], 4); // System.out.println("Over:收到包,str"+str); String str = Encoding.Default.GetString(receiveBuffer, StopTip[1], 4); //if (str.equals(datagramStop)) if (datagramStop.Equals(str)) { //检查次随机数 int num = ByteChange.ByteToInt(receiveBuffer, StopTip[2]); if (num == numberRandom) { canSendAck = true; continue; } } //如果收到开始传输包,并且其次随机数与这次的不一样,则退出 //if (str.equals(datagramStart)) if (datagramStart.Equals(str)) { //检查次随机数 if (ByteChange.ByteToInt(receiveBuffer, StartTip[2]) != numberRandom) { break; } } //如果是其他包,也继续循环,但是一下轮不发送确认包 canSendAck = false; continue; } catch (Exception e) { if (e is TimeoutException) { //如果接收超时,则退出循环 // System.out.println("接收超时"); break; } if (e is SocketException) { break; } } } }
/*接收一个分组*/ /*返回值说明: * 1.如果正常接收,返回读取数据的长度 * 2.如果接收超时,返回-1 //此句已经无效 * 3.如果接收到本分组的分组头,返回-2 * 4.如果接收到新的发送完毕包,返回-3 * 5.如果接收到上次的发送完毕包,返回-4 * 6.其他情况,返回-5 */ //此函数只用于接收,不发送任何信息.遇到错误,只是将错误标识返回. //如果接收到的是分组包,将其存入buffer中相应位置,返回数据的长度 public int GetDatagramData(int numberRandom, int random, byte[] buffer, bool[] receiveTip, int[] startTip) { //设置不接收超时 //try //{ // socket.setSoTimeout(0); //} //catch (SocketException ex) //{ // // Logger.getLogger(ReceiveLittle.class.getName()).log(Level.SEVERE, null, ex); // logger.error("{}", ex); //} udpReceiveClient.Client.ReceiveTimeout = 0; byte[] receiveBuffer = new byte[DataTip[0]]; //DatagramPacket packet = new DatagramPacket(receiveBuffer, receiveBuffer.length); try { ByteChange.CleanByte(receiveBuffer); //socket.receive(packet); receiveBuffer = udpReceiveClient.Receive(ref host); //receiveState.addHaveReceiveBytes(packet.getLength()); //就算收到未接收请求重发包,有意义的随机数也应该是与本分组随机数相同的 //次随机数 if (ByteChange.ByteToInt(receiveBuffer, DataTip[2]) != numberRandom) { return(-5); } //所以,先判断块随机数 int r = ByteChange.ByteToInt(receiveBuffer, DataTip[3]); if (r != random) { return(-5); } //判断分组标识 //String s = new String(receiveBuffer, DataTip[1], 4); String s = Encoding.Default.GetString(receiveBuffer, DataTip[1], 4); //if (!s.equals(datagramData)) if (!datagramData.Equals(s)) { //如果此包不是分组包 //判断其是否是本分组的分组头.由于随机数已经匹配,所以,只需要判断标识 //if (s.equals(datagramHead)) if (datagramHead.Equals(s)) { return(-2); } //再判断其是否是发送完毕包 //if (s.equals(datagramFinish)) if (datagramFinish.Equals(s)) { //先判断,是否是新的发送完毕包 r = ByteChange.ByteToInt(receiveBuffer, FinishTip[4]); if (!littleRandomStack.InIt(r)) { littleRandomStack.Add(r); return(-3); } //如果是上次的发送完毕包 int r2 = littleRandomStack.GetLast(); if (r2 != -1 && r2 == r) { return(-4); } } //否则,返回-5 return(-5); } //至此已经是分组包了,先判断一下包的完整性 //因为,如果包是不完整的,它的数据就是有问题的,是不能接收的 //s = new String(receiveBuffer, DataTip[7], 4); s = Encoding.Default.GetString(receiveBuffer, DataTip[7], 4); //if (!s.equals(datagramTail)) if (!datagramTail.Equals(s)) { return(-5); } //包是完整的,获取包的序号 int serial = ByteChange.ByteToShort(receiveBuffer, DataTip[4]); int number = ByteChange.ByteToShort(receiveBuffer, DataTip[5]); //如果该序列的包未被正确接收 if (!receiveTip[serial]) { receiveTip[serial] = true; for (int i = 0; i < number; i++) { buffer[i + startTip[serial]] = receiveBuffer[i + DataTip[6]]; } return(number); } //如果已经被正确接收了,则丢弃该包 else { return(-5); } } catch (Exception ex) { //Logger.getLogger(Receive.class.getName()).log(Level.SEVERE, null, ex); if (ex is TimeoutException) { return(-1); } if (ex is SocketException) { return(-1); } return(-5); } }
/*接收分组头*/ //1.不接收超时. 2.接收成功,会调用发送分组头确认包 public Rdh_return ReceiveDatagramHead(int numberRandom) { byte[] buffer = new byte[FilePropertyTip[0]]; //DatagramPacket packet = null; Rdh_return rdh = new Rdh_return(); //设置不接收超时 udpReceiveClient.Client.ReceiveTimeout = 0; while (true) { try { //packet = new DatagramPacket(buffer, buffer.length);//,InetAddress.getByName(yourAddress),yourPort ByteChange.CleanByte(buffer); //socket.receive(packet); //receiveState.addHaveReceiveBytes(packet.getLength()); buffer = udpReceiveClient.Receive(ref host); //检查分组头标识 //String str = new String(buffer, HeadTip[1], 4); String str = Encoding.Default.GetString(buffer, HeadTip[1], 4); //if (!str.equals(datagramHead)) if (!datagramHead.Equals(str)) { /*既然不是分组头,重新接收是肯定的.只不过,有些情况,需要处理一下再重新接收*/ //如果是开始传输包 //if (str.equals(datagramStart)) if (datagramStart.Equals(str)) { int num = ByteChange.ByteToInt(buffer, StartTip[2]); if (num == numberRandom) { SendStartAck(numberRandom); // System.out.println("在分组头中接收到开始传输包"); continue; } } //如果是发送完毕包 //if (str.equals(datagramFinish)) if (datagramFinish.Equals(str)) { //先检其次随机数 if (ByteChange.ByteToInt(buffer, FinishTip[2]) == numberRandom) { //检验是不是上一次的发送完毕包 //如果是的,说明上次发的0请求重发包没发成功 //先检查其块随机数是不是上一次的 if (randomStack.GetLast() != -1 && ByteChange.ByteToInt(buffer, FinishTip[3]) == randomStack.GetLast()) { //再检查其小随机数,是不是上次的(即最后一次发过来的) if (littleRandomStack != null) { //如果littelRandomStack是null,说明这是第一次接收分组头,当然不可能要重发 if (littleRandomStack.GetLast() == ByteChange.ByteToInt(buffer, FinishTip[4])) { //如果小随机数也匹配,则发送上次的0请求重发包 if (lastReqAgainBuffer != null) { //socket.send(lastReqAgain); udpReceiveClient.Send(lastReqAgainBuffer.ToArray(), lastReqAgainBuffer.Count, host); } } } } } } //如果是传输结束包,则将0分组数量填充入rdh,然后返回 //if (str.equals(datagramStop)) if (datagramStop.Equals(str)) { rdh.Number = 0; return(rdh); } continue; } //检查该包是否完整 //str = new String(buffer, HeadTip[5], 4); str = Encoding.Default.GetString(buffer, HeadTip[5], 4); //if (!str.equals(datagramTail)) if (!datagramTail.Equals(str)) { continue; } //检查完毕,获取随机数 rdh.Random = ByteChange.ByteToInt(buffer, HeadTip[3]); //获取分组数量 rdh.Number = ByteChange.ByteToShort(buffer, HeadTip[4]); SendDatagramHeadAck(numberRandom, rdh.Random); break; } catch (Exception ex) { //MessageBox.Show(ex.ToString()); // Logger.getLogger(ReceiveLittle.class.getName()).log(Level.SEVERE, null, ex); //logger.error("{}", ex); } } return(rdh); }