日本好好热aⅴ|国产99视频精品免费观看|日本成人aV在线|久热香蕉国产在线

  • <cite id="ikgdy"><table id="ikgdy"></table></cite>
    1. 西西軟件下載最安全的下載網(wǎng)站、值得信賴的軟件下載站!

      首頁(yè)編程開(kāi)發(fā)C#.NET → C#實(shí)現(xiàn)UDP數(shù)據(jù)包大文件分包傳輸和接收組包

      C#實(shí)現(xiàn)UDP數(shù)據(jù)包大文件分包傳輸和接收組包

      前往專題相關(guān)軟件相關(guān)文章發(fā)表評(píng)論 來(lái)源:西西整理時(shí)間:2013/4/14 9:13:09字體大。A-A+

      作者:西西點(diǎn)擊:0次評(píng)論:0次標(biāo)簽: UDP

      • 類型:網(wǎng)絡(luò)共享大。1.4M語(yǔ)言:英文 評(píng)分:5.0
      • 標(biāo)簽:
      立即下載

      如果需要使用UDP傳輸較大數(shù)據(jù),例如傳輸10M的圖片,這突破了UDP的設(shè)計(jì)原則。UDP的設(shè)計(jì)是基于"datagram",也就是它假設(shè)你發(fā)送的每個(gè)數(shù)據(jù)包都能包含在單一的包內(nèi)。并且設(shè)定UDP數(shù)據(jù)包的最大長(zhǎng)度受基礎(chǔ)網(wǎng)絡(luò)協(xié)議的限制。

      UDP數(shù)據(jù)包的理論最大長(zhǎng)度限制是 65535 bytes,這包含 8 bytes 數(shù)據(jù)包頭和 65527 bytes 數(shù)據(jù)。但如果基于IPv4網(wǎng)絡(luò)傳輸,則還需減去 20 bytes 的IP數(shù)據(jù)包頭。
      則單一的UDP數(shù)據(jù)包可傳輸?shù)臄?shù)據(jù)最大長(zhǎng)度為:

      MaxUdpDataLength = 65535 - 8 - 20 = 65507 bytes

      這就需要實(shí)現(xiàn)UDP包的分包傳輸和接收組包功能。

      分包功能

      1 /// <summary>

       2   /// UDP數(shù)據(jù)包分割器
       3   /// </summary>
       4   public static class UdpPacketSplitter
       5   {
       6     /// <summary>
       7     /// 分割UDP數(shù)據(jù)包
       8     /// </summary>
       9     /// <param name="sequence">UDP數(shù)據(jù)包所持有的序號(hào)</param>
      10     /// <param name="datagram">被分割的UDP數(shù)據(jù)包</param>
      11     /// <param name="chunkLength">分割塊的長(zhǎng)度</param>
      12     /// <returns>
      13     /// 分割后的UDP數(shù)據(jù)包列表
      14     /// </returns>
      15     public static ICollection<UdpPacket> Split(long sequence, byte[] datagram, int chunkLength)
      16     {
      17       if (datagram == null)
      18         throw new ArgumentNullException("datagram");
      19 
      20       List<UdpPacket> packets = new List<UdpPacket>();
      21 
      22       int chunks = datagram.Length / chunkLength;
      23       int remainder = datagram.Length % chunkLength;
      24       int total = chunks;
      25       if (remainder > 0) total++;
      26 
      27       for (int i = 1; i <= chunks; i++)
      28       {
      29         byte[] chunk = new byte[chunkLength];
      30         Buffer.BlockCopy(datagram, (i - 1) * chunkLength, chunk, 0, chunkLength);
      31         packets.Add(new UdpPacket(sequence, total, i, chunk, chunkLength));
      32       }
      33       if (remainder > 0)
      34       {
      35         int length = datagram.Length - (chunkLength * chunks);
      36         byte[] chunk = new byte[length];
      37         Buffer.BlockCopy(datagram, chunkLength * chunks, chunk, 0, length);
      38         packets.Add(new UdpPacket(sequence, total, total, chunk, length));
      39       }
      40 
      41       return packets;
      42     }
      43   }

      發(fā)送分包

       1 private void WorkThread()

       2 {
       3   while (IsRunning)
       4   {
       5     waiter.WaitOne();
       6     waiter.Reset();
       7 
       8     while (queue.Count > 0)
       9     {
      10       StreamPacket packet = null;
      11       if (queue.TryDequeue(out packet))
      12       {
      13         RtpPacket rtpPacket = RtpPacket.FromImage(
      14           RtpPayloadType.JPEG, 
      15           packet.SequenceNumber, 
      16           (long)Epoch.GetDateTimeTotalMillisecondsByYesterday(packet.Timestamp),
      17           packet.Frame);
      18 
      19         // max UDP packet length limited to 65,535 bytes
      20         byte[] datagram = rtpPacket.ToArray(); 
      21         packet.Frame.Dispose();
      22 
      23         // split udp packet to many packets 
      24         // to reduce the size to 65507 limit by underlying IPv4 protocol
      25         ICollection<UdpPacket> udpPackets 
      26           = UdpPacketSplitter.Split(
      27             packet.SequenceNumber, 
      28             datagram, 
      29             65507 - UdpPacket.HeaderSize);
      30         foreach (var udpPacket in udpPackets)
      31         {
      32           byte[] udpPacketDatagram = udpPacket.ToArray();
      33           // async sending
      34           udpClient.BeginSend(
      35             udpPacketDatagram, udpPacketDatagram.Length,
      36             packet.Destination.Address,
      37             packet.Destination.Port,
      38             SendCompleted, udpClient);
      39         }
      40       }
      41     }
      42   }
      43 }

      接收組包功能

       1 private void OnDatagramReceived(object sender, UdpDatagramReceivedEventArgs<byte[]> e)

       2     {
       3       try
       4       {
       5         UdpPacket udpPacket = UdpPacket.FromArray(e.Datagram);
       6 
       7         if (udpPacket.Total == 1)
       8         {
       9           RtpPacket packet = new RtpPacket(udpPacket.Payload, udpPacket.PayloadSize);
      10           Bitmap bitmap = packet.ToBitmap();
      11           RaiseNewFrameEvent(
      12             bitmap, Epoch.GetDateTimeByYesterdayTotalMilliseconds(packet.Timestamp));
      13         }
      14         else
      15         {
      16           // rearrange packets to one packet
      17           if (packetCache.ContainsKey(udpPacket.Sequence))
      18           {
      19             List<UdpPacket> udpPackets = null;
      20             if (packetCache.TryGetValue(udpPacket.Sequence, out udpPackets))
      21             {
      22               udpPackets.Add(udpPacket);
      23 
      24               if (udpPackets.Count == udpPacket.Total)
      25               {
      26                 packetCache.TryRemove(udpPacket.Sequence, out udpPackets);
      27 
      28                 udpPackets = udpPackets.OrderBy(u => u.Order).ToList();
      29                 int rtpPacketLength = udpPackets.Sum(u => u.PayloadSize);
      30                 int maxPacketLength = udpPackets.Select(u => u.PayloadSize).Max();
      31 
      32                 byte[] rtpPacket = new byte[rtpPacketLength];
      33                 foreach (var item in udpPackets)
      34                 {
      35                   Buffer.BlockCopy(
      36                     item.Payload, 0, rtpPacket, 
      37                     (item.Order - 1) * maxPacketLength, item.PayloadSize);
      38                 }
      39 
      40                 RtpPacket packet = new RtpPacket(rtpPacket, rtpPacket.Length);
      41                 Bitmap bitmap = packet.ToBitmap();
      42                 RaiseNewFrameEvent(
      43                   bitmap, 
      44                   Epoch.GetDateTimeByYesterdayTotalMilliseconds(packet.Timestamp));
      45 
      46                 packetCache.Clear();
      47               }
      48             }
      49           }
      50           else
      51           {
      52             List<UdpPacket> udpPackets = new List<UdpPacket>();
      53             udpPackets.Add(udpPacket);
      54             packetCache.AddOrUpdate(
      55               udpPacket.Sequence, 
      56               udpPackets, (k, v) => { return udpPackets; });
      57           }
      58         }
      59       }
      60       catch (Exception ex)
      61       {
      62         RaiseVideoSourceExceptionEvent(ex.Message);
      63       }
      64     }

        相關(guān)評(píng)論

        閱讀本文后您有什么感想? 已有人給出評(píng)價(jià)!

        • 8 喜歡喜歡
        • 3 頂
        • 1 難過(guò)難過(guò)
        • 5 囧
        • 3 圍觀圍觀
        • 2 無(wú)聊無(wú)聊

        熱門(mén)評(píng)論

        最新評(píng)論

        發(fā)表評(píng)論 查看所有評(píng)論(0)

        昵稱:
        表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
        字?jǐn)?shù): 0/500 (您的評(píng)論需要經(jīng)過(guò)審核才能顯示)