/*接收分组头*/
        //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);
        }
        /*接收一次分组*/
        //返回值为该数组中数据的长度.并且,此函数进行传送结束的检查.发现结束,返回-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);
        }