コード例 #1
0
ファイル: UdpFileReceiver.cs プロジェクト: palecek777/PSIApp
        private void OnClientDataReceived(object sender, DataReceivedEventArgs e)
        {
            if (!MessageConstructor.ValidateMessage(e.Data))
            {
                if (StopAndWait)
                {
                    byte[] msg = MessageConstructor.GetDataReceived(uint.MinValue, uint.MaxValue);
                    Client.Send(msg, msg.Length);
                }

                return;
            }

            if (MessageConstructor.IsHandshake(e.Data))
            {
                Connect(BitConverter.ToUInt32(e.Data, 1), BitConverter.ToUInt32(e.Data, 1 + sizeof(int)), e.EndPoint);
                return;
            }

            if (IsTransfering && MessageConstructor.IsFileData(e.Data))
            {
                ReceivePacket(MessageConstructor.GetPacket(e.Data));
                return;
            }

            if (MessageConstructor.IsFileMeta(e.Data))
            {
                TotalPacketCount = BitConverter.ToUInt32(e.Data, 1 + sizeof(long));


                string fn = Encoding.ASCII.GetString(e.Data, 1 + sizeof(long) + sizeof(uint), e.Data.Length - 1 - sizeof(long) - sizeof(uint) - sizeof(uint));
                PrepareFile(fn);

                ReceivedPackets = new DataPacket[TotalPacketCount];

                Console.WriteLine($"Receiving file '{fn}', total of {TotalPacketCount} packets.");
                WriteStatus(0, TotalPacketCount, false);
                Client.Send(e.Data, e.Data.Length);

                //Client.ErrorRate = 0.001;
                //Client.DropRate = 0.01;
            }

            if (IsTransfering && MessageConstructor.IsFileEnd(e.Data))
            {
                WriteFile();

                uint hash = BitConverter.ToUInt32(e.Data, 1);

                uint computed = MessageConstructor.GetFileHash(FileName);

                if (hash == computed)
                {
                    FileReceived?.Invoke(this, new FileReceivedEventArgs()
                    {
                        FileName = FileName
                    });
                    _is_transfering = false;
                }
                else
                {
                    Console.WriteLine("Something is wrong, received different hash.");
                    _is_transfering = false;
                }
            }
        }
コード例 #2
0
ファイル: UdpFileSender.cs プロジェクト: palecek777/PSIApp
        //uint last_ack = 0;
        public void SendFile(string path)
        {
            DeliveredPacketCount = 0;
            _is_transfering      = true;
            string file_name = Path.GetFileName(path);

            int buffer_size = (int)MaxPacketLength - DataPacket.MiscLength;

            // poslu FileMeta msg a pockam na odpoved - Handshake se stejnymi hodnotami
            FileInfo finfo    = new FileInfo(path);
            uint     pack_cnt = (uint)(finfo.Length / buffer_size + (finfo.Length % buffer_size > 0 ? 1 : 0));

            //zkratit file_name, aby se veslo do maximalni delky packetu
            if (file_name.Length > (MaxPacketLength - sizeof(byte) - sizeof(long) - sizeof(int) - sizeof(uint)))
            {
                file_name = file_name.Substring((int)(MaxPacketLength - sizeof(byte) - sizeof(long) - sizeof(int) - sizeof(uint)));
            }

            byte[] msg = MessageConstructor.GetFileMeta(finfo.Length, pack_cnt, file_name);
            Client.Send(msg, msg.Length, Target);

            while (meta_response == null)
            {
            }

            if (!Extensions.AreSameArrays(msg, meta_response))
            {
                meta_response = null;
                throw new Exception("Invalid FileMeta response");
            }

            meta_response = null;

            // kdykoliv to bude mozne, tak budu posilat packety...
            // array - vsechny aktualni nepotvrzene packety
            uint packet_num = 0;

            // v tomto HashSetu jsou indexy packetu, ktere jsou potvrzene, tudiz je mozne je pouzit
            AckPackets = new HashSet <int>();
            for (int i = 0; i < MaxPackets; ++i)
            {
                AckPackets.Add(i);
            }


            //int buffer_size = (int)MaxPacketLength - //packet length
            //                  1 -               //packet type
            //                  sizeof(uint) -     //number of packet
            //                  sizeof(uint) -     //data length
            //                  sizeof(uint);     //CRC


            //indkuje, ze je potreba zrusit nejaky cyclus, pouziti ruzne
            bool break_cycle;

            WriteStatus(DeliveredPacketCount, pack_cnt, false);

            Client.ErrorRate = 0.1;
            Client.DropRate  = 0.1;

            using (BinaryReader reader = new BinaryReader(File.Open(path, FileMode.Open, FileAccess.Read)))
            {
                byte[] read_buffer = new byte[buffer_size];
                while (reader.BaseStream.Position != reader.BaseStream.Length)
                {
                    int act_count = reader.Read(read_buffer, 0, buffer_size);

                    if (act_count < 0)
                    {
                    }

                    // cekam na volny packet
                    int idx;
                    while (true)
                    {
                        PacketsMutex.WaitOne();
                        break_cycle = AckPackets.Count > 0;
                        PacketsMutex.ReleaseMutex();
                        if (break_cycle)
                        {
                            break;
                        }
                        Thread.Sleep(20);
                    }

                    PacketsMutex.WaitOne();
                    idx = AckPackets.Pop();
                    PacketsMutex.ReleaseMutex();

                    //Nastvaim hodnoty volneho packetu
                    // nemelo by byt potreba nastavovat PacketMutext, protoze jina vlakna by v tento moment nemela pristupovat k datum ktera chci upravovat
                    //PacketsMutex.WaitOne();

                    Packets[idx].Data     = MessageConstructor.GetFileData(packet_num, read_buffer, (uint)act_count);
                    Packets[idx].Number   = packet_num;
                    Packets[idx].AckCount = 0;

                    //PacketsMutex.ReleaseMutex();

                    Client.SendPacket(Packets[idx], Target);

                    //zvysuji cislo packetu
                    packet_num++;

                    WriteStatus(DeliveredPacketCount, pack_cnt);
                }
            }

            //v tento moment jsou vsechnz packety dorucene ci na ceste, cekam na ack vsech prave posilanych

            while (true)
            {
                PacketsMutex.WaitOne();
                // tedy vsechny packety jsou volne
                break_cycle = AckPackets.Count >= MaxPackets;
                PacketsMutex.ReleaseMutex();
                WriteStatus(DeliveredPacketCount, pack_cnt);
                if (break_cycle)
                {
                    break;
                }
                Thread.Sleep(20);
            }

            // poslu FileEnd msg
            //TODO: vypocet File hash
            byte[] file_end = MessageConstructor.GetFileEnd(MessageConstructor.GetFileHash(file_name));
            Client.Send(file_end, file_end.Length, Target);

            // jine vlakno prijme reakci na file_end message a pokud to nebude uspokojiva odpoved, zopakuje zaslani...
        }