/**
         * 接收文件属性包
         * @return
         */
        //public FileProperty receiveFileProperty()
        //{
        //    //DatagramPacket receivePacket = null;
        //    //用于接收开始传输包
        //    byte[] receiveBuffer = new byte[FilePropertyTip[0]];
        //    try
        //    {
        //        //socket.setSoTimeout(0);
        //        //receivePacket = new DatagramPacket(receiveBuffer, receiveBuffer.length);
        //        udpReceiveClient.Client.ReceiveTimeout = 0;
        //    }
        //    catch (Exception e) {

        //    }
        //    while (true)
        //    {
        //        try
        //        {
        //            //socket.receive(receivePacket);
        //            //receiveState.addHaveReceiveBytes(receivePacket.getLength());
        //            receiveBuffer = udpReceiveClient.Receive(ref host);
        //            //检查标识
        //            //String str = new String(receiveBuffer, FilePropertyTip[1], 4);
        //            String str = Encoding.Default.GetString(receiveBuffer, FilePropertyTip[1], 4);
        //            //if (!str.equals(datagramFileProperty))
        //            if(!datagramFileProperty.Equals(str))
        //            {
        //                continue;
        //            }
        //            FileProperty fp = new FileProperty();
        //            //获取次随机数
        //            int numberRandom = ByteChange.byteToInt(receiveBuffer, FilePropertyTip[2]);
        //            fp.FileLength = ByteChange.byteToLong(receiveBuffer, FilePropertyTip[3]);
        //            int fileNameLength = ByteChange.byteToInt(receiveBuffer, FilePropertyTip[4]);
        //            fp.FileName = ByteChange.ByteToString(receiveBuffer, FilePropertyTip[5], fileNameLength);
        //            fp.MD5Str = ByteChange.ByteToString(receiveBuffer, FilePropertyTip[6], 32);
        //            receiveState.setFileLength(fp.FileLength);
        //            File f = new File(fp.FileName);
        //            if (f.exists())
        //            {
        //                logger.info("send md5:{}+receive md5:{}", fp.MD5Str, MD5.getFileMD5String(f));
        //                receiveState.setExistFileLength(f.length());
        //                if (fp.FileLength > f.length())
        //                {
        //                    fp.isOver = false;
        //                    fp.isExists = true;
        //                    logger.info("文件已存在,开始断点续传");
        //                    sendBreakPoint(numberRandom, f, fp);
        //                }
        //                else if (fp.FileLength == f.length())
        //                {
        //                    if (fp.MD5Str.equals(MD5.getFileMD5String(f)))
        //                    {//MD5一样
        //                        fp.isOver = true;
        //                        fp.isExists = true;
        //                        logger.info("文件已传输完成");
        //                        sendBreakPoint(numberRandom, f, fp);
        //                    }
        //                    else
        //                    {
        //                        fp.isOver = false;
        //                        fp.isExists = false;
        //                        logger.info("文件出错,重新接受");
        //                        sendFilePropertyAck(numberRandom);
        //                    }
        //                }
        //                else
        //                {
        //                    fp.isOver = false;
        //                    fp.isExists = false;
        //                    logger.info("文件出错,重新接受");
        //                    sendFilePropertyAck(numberRandom);
        //                }
        //            }
        //            else
        //            {
        //                fp.isOver = false;
        //                fp.isExists = false;
        //                sendFilePropertyAck(numberRandom);
        //                System.out.println("文件不存在,接收到文件属性包");
        //            }
        //            return fp;
        //        }
        //        catch (Exception ex)
        //        {
        //            //                Logger.getLogger(ReceiveLittle.class.getName()).log(Level.SEVERE, null, ex);
        //            logger.error("{}", ex);
        //        }
        //    }
        //}

        //private void SendBreakPoint(int numberRandom, File f, FileProperty fp)
        //{
        //    DatagramPacket sendPacket = null;
        //    byte sendBuffer[] = new byte[FileBreakPointTip[0]];
        //    //填充标识
        //    ByteChange.StringToByte(datagramFileBreakPoint, sendBuffer, FileBreakPointTip[1], 4);
        //    //填充次随机数
        //    ByteChange.intToByte(sendBuffer, FileBreakPointTip[2], numberRandom);
        //    //填充文件长度
        //    ByteChange.longToByte(sendBuffer, FileBreakPointTip[3], fp.FileLength);
        //    //填充已传文件长度
        //    ByteChange.longToByte(sendBuffer, FileBreakPointTip[4], f.length());
        //    //填充报尾
        //    ByteChange.StringToByte(datagramTail, sendBuffer, FileBreakPointTip[5], 4);
        //    try
        //    {
        //        sendPacket = new DatagramPacket(sendBuffer, sendBuffer.length, InetAddress.getByName(yourAddress), yourPort);
        //        socket.send(sendPacket);
        //    }
        //    catch (Exception ex)
        //    {
        //        //            Logger.getLogger(ReceiveLittle.class.getName()).log(Level.SEVERE, null, ex);
        //        logger.error("{}", ex);
        //    }
        //}
        //
        //	private int punchDirectAckToClient(DatagramPacket dp, byte[] receiveBuffer) {
        //		// TODO Auto-generated method stub
        //		int randNum = ByteChange.byteToInt(receiveBuffer, CTCPunchDirectTip[2]);
        //		long sID = ByteChange.byteToLong(receiveBuffer, CTCPunchDirectTip[3]);
        //		long rID = ByteChange.byteToLong(receiveBuffer, CTCPunchDirectTip[4]);
        //		String strTail=new String(receiveBuffer,CTCPunchDirectTip[5],4);
        //		if(!strTail.equals(datagramTail)){
        //			return -1;
        //		}
        //		DatagramPacket sendPacket = null;
        //		byte sendBuffer[] = new byte[CTCPunchDirectAckTip[0]];
        //		// 填充开始传输包
        //		ByteChange.StringToByte(datagramCTCPunchDirectAck, sendBuffer, CTCPunchDirectAckTip[1], 4);
        //		ByteChange.intToByte(sendBuffer, CTCPunchDirectAckTip[2], randNum);
        //		ByteChange.longToByte(sendBuffer, CTCPunchDirectAckTip[3], sID);
        //		ByteChange.longToByte(sendBuffer, CTCPunchDirectAckTip[4], rID);
        //		ByteChange.StringToByte(datagramTail, sendBuffer, CTCPunchDirectAckTip[5], 4);
        //		try {
        //			System.out.println("sendAck="+datagramCTCPunchDirectAck+randNum+sID+rID+datagramTail+dp.getAddress()+dp.getPort());
        //			sendPacket = new DatagramPacket(sendBuffer, sendBuffer.length, dp.getAddress(),dp.getPort());
        //			socket.send(sendPacket);
        //		} catch (Exception e) {
        //			// TODO Auto-generated catch block
        //			e.printStackTrace();
        //		}
        //
        //		return 1;
        //	}
        /*发送文件属性确认包*/
        //public void sendFilePropertyAck(int numberRandom)
        //{
        //    DatagramPacket sendPacket = null;
        //    byte sendBuffer[] = new byte[FilePropertyAckTip[0]];
        //    //填充标识
        //    ByteChange.StringToByte(datagramFilePropertyAck, sendBuffer, FilePropertyAckTip[1], 4);
        //    //填充次随机数
        //    ByteChange.intToByte(sendBuffer, FilePropertyAckTip[2], numberRandom);
        //    //填充报尾
        //    ByteChange.StringToByte(datagramTail, sendBuffer, FilePropertyAckTip[3], 4);
        //    try
        //    {
        //        sendPacket = new DatagramPacket(sendBuffer, sendBuffer.length, InetAddress.getByName(yourAddress), yourPort);
        //        socket.send(sendPacket);
        //    }
        //    catch (Exception ex)
        //    {
        //        //            Logger.getLogger(ReceiveLittle.class.getName()).log(Level.SEVERE, null, ex);
        //        logger.error("{}", ex);
        //    }
        //}
        //文件属性内部类
        //public class FileProperty
        //{
        //    public boolean isOver;
        //    public long FileLength;
        //    public String FileName;
        //    public String MD5Str;
        //    public boolean isExists;

        //    FileProperty()
        //    {
        //        isOver = false;
        //        FileLength = 0;
        //        isExists = false;
        //    }
        //}

        /*分组接收*/
        public int ReceiveAll(byte[] littleBuffer)
        {
            byte[] buffer = new byte[dataLength * groupNum];
            randomStack = new CircleStack(100);
            int numberRandom = ReceiveStart();//接收开始传输包
            int allLength    = 0;

            while (true)
            {
                int length = ReceiveGroup(numberRandom, buffer);
                if (length != -1)
                {
                    for (int i = 0; i < length; i++)
                    {
                        littleBuffer[i + allLength] = buffer[i];
                    }
                    allLength += length;
                }
                else
                {
                    SendOverAck(numberRandom);
                    //                if(allLength==3){
                    //                    String end=new String(littleBuffer,0,3);
                    //                    System.out.println("end-->"+end);
                    //                }
                    //receiveState.addHavaReceivefileLength(allLength);
                    return(allLength);
                }
            }
        }
        /*接收一次分组*/
        //返回值为该数组中数据的长度.并且,此函数进行传送结束的检查.发现结束,返回-1
        public int ReceiveGroup(int numberRandom, byte[] buffer)
        {
            //接收分组头
            Rdh_return rdh = ReceiveDatagramHead(numberRandom);
            //       System.out.println("收到分组头,随机数:"+rdh.random+",分组数量:"+rdh.number);
            //记下随机数及分组数量
            //int random = rdh.random;
            //int number = rdh.number;
            int random = rdh.Random;
            int number = rdh.Number;

            if (number == 0)
            {
                return(-1);
            }
            randomStack.Add(random);
            littleRandomStack = new CircleStack(100);
            //设定数据总长度
            int lengthAll = 0;

            //由于只有最后一组的数据长度不是dataLength,所以,先计算前number-1个分组的总长度
            lengthAll = dataLength * (number - 1);
            //用于记录成功接收了哪些分组
            bool[] receiveTip = new bool[number];
            for (int i = 0; i < number; i++)
            {
                receiveTip[i] = false;
            }
            //预先计算各组应存入buffer的起始下标
            //由于除了最后一组,其它组的数据长度一定是dataLength.所以计算起始下标非常简单
            int[] startTip = new int[number];
            for (int i = 0; i < number; i++)
            {
                startTip[i] = i * dataLength;
            }
            //进入大循环,即连续去接收分组,直到所有分组完毕
            while (true)
            {
                int result = GetDatagramData(numberRandom, random, buffer, receiveTip, startTip);
                //            System.out.println("收到分组包"+result);
                //如果接收到的是一个分组.要记录其长度.由于,除了最后一组,其他的长度一定是dataLength
                //所以,如果这个length不是dataLength,说明是最后一组的长度
                if (result > 0)
                {
                    if (result != dataLength)
                    {
                        lengthAll += result;
                    }
                    continue;
                }
                //如果接收到是分组头
                else if (result == -2)
                {
                    //发送分组头确认包,然后循环
                    SendDatagramHeadAck(numberRandom, random);
                    continue;
                }
                //如果是新的发送完毕包
                else if (result == -3)
                {
                    //发送请求重发包
                    //在发送请求重发包的时候,是要检查是否全部成功接收的,所以,这里不再重新检查,而是使用它检查的结果
                    bool flag = SendDatagramReqAgain(numberRandom, random, littleRandomStack.GetLast(), receiveTip);
                    //System.out.println("发送请求重发包");
                    if (flag)
                    {
                        break;
                    }
                    continue;
                }
                //如果是上次的发送完毕包
                else if (result == -4)
                {
                    //如果上次发送的不是0请求重发包,则重发
                    //非0请求重发包的长度,一定是1018
                    //System.out.println("接收到上次的发送完毕包:");
                    try
                    {
                        if (lastReqAgainBuffer.Count == ReqAgainTip[0])
                        {
                            //System.out.println("重发非0请求重发包");
                            //socket.send(lastReqAgain);

                            udpReceiveClient.Send(lastReqAgainBuffer.ToArray(), lastReqAgainBuffer.Count, host);
                        }
                    }
                    catch (Exception ex)
                    {
                        log.Error(ex.ToString());
                        //MessageBox.Show(ex.ToString());
                        //                        Logger.getLogger(ReceiveLittle.class.getName()).log(Level.SEVERE, null, ex);
                        //logger.error("{}", ex);
                    }
                    continue;
                }
            }
            //这里有个很蛋疼的问题.由于不确定最后一组是否完整,只有在接收到最后一个分组时才知道其数据长度
            //而接收分组是在单独的函数中完成,函数返回的是接收的数据长度.在循环中,如果发现数据长度不是dataLength
            //就认为它是最后一组,并将其长度加入lengthAll.但是,有一个严重的问题,因为,每个块,只有最后一个块的最后一个
            //分组的数据长度可能不是dataLength.所以,前面的块,在进行计算的时候,有会忽略它最后一组的长度.导致以后的块
            //连续错误
            if (lengthAll == (number - 1) * dataLength)
            {
                lengthAll += dataLength;
            }
            return(lengthAll);
        }