C#基于Udp的分包传输

   因为要远做程摄像头监控,要用到网络数据传输,百度了一下,很多就是基于Tcp的,因为QQ是用Udp,所有我也尝试用Udp。

要用Udp传输数据,就免不了分包和重包,因为Udp最大只能传输64KB的数据!下面给出分包的代码:

   首先定义一个包类:

using System;
using System.Collections.Generic;

namespace Packet_Library
{

    /// <summary>
    /// 包类
    /// </summary>
    public class Packet
    {
        private int  _index;
        private byte[]  _data;
        private int  _state;
        public Packet(int index, byte[] buffer,int state)
        {
            this._index = index;
            this._data = buffer;
            this._state = state;
        }
        /// <summary>
        /// 索引序号
        /// </summary>
        public int Index
        {
            get { return _index; }
            set { _index = value; }
        }
        /// <summary>
        /// 数据
        /// </summary>
        public byte[] Data
        {
            get { return _data; }
            set { _data = value; }
        }
        /// <summary>
        /// 状态,用来记录包的开始和结束。1:开始,2:中间,3:包尾。
        /// </summary>
        public int State
        {
            get { return _state; }
            set { _state = value; }
        }
    }

}

再定义一个处理包的类:

using System;
using System.Collections.Generic;

namespace Packet_Library
{
    /// <summary>
    /// 分包
    /// </summary>
    public class PacketSplitter
    {
        private static int defaultPartSize = 1024;
        /// <summary>
        /// 分包
        /// </summary>
        /// <param name="datagram">数据包</param>
        /// <param name="partSize">块大小(小于1024*64)</param>
        /// <returns>分包列表</returns>
        public static List<Packet> Split(byte[] datagram, int partSize)
        {
            defaultPartSize = partSize;
            return Split(datagram);

        }

        /// <summary>
        /// 分包
        /// </summary>
        /// <param name="datagram">数据包(使用默认块大小:1024 byte)</param>
        /// <returns>分包列表</returns>
        public static List<Packet> Split(byte[] datagram)
        {
            List<Packet> packets = new List<Packet>();
            if (datagram == null)
                return null;
            if (datagram.Length <= defaultPartSize)
            {
                packets.Add(new Packet(0, datagram, 1));
                return packets;
            }
            int _length = datagram.Length;
            int counts = _length / defaultPartSize;
            int remainder = _length % defaultPartSize;
            int tatal = counts;
            if (remainder > 0)
                counts++;
            for (int i = 0; i < counts; i++)
            {
                int _size = defaultPartSize;
                if (_length - defaultPartSize * i < defaultPartSize)
                    _size = _length - defaultPartSize * i;
                byte[] tmp = new byte[_size];
                Buffer.BlockCopy(datagram, defaultPartSize * i, tmp, 0, _size);
                int state = 2;
                if (i == 0)
                    state = 1;
                if (i == counts - 1)
                    state = 3;
                packets.Add(new Packet(i, tmp, state));
            }
            return packets;
        }
    }
}

因为Udp是无连接的,所以我也模拟握手方式来进行数据传输,不要跟我说什么是握手,如果真的不知道的话,那我就再啰嗦几句。所谓握手是一个连接方式,就像我们打电话,首先你拔号,再等待,如果对方接了,你们才可以通话。Tcp就是这样的!

在Udp[中,我们可以先定义几个指令:

public Enum Commands{

requestVideoCapital=1,//请求获取视频

requestSendPacket=2,//请求发送数据包

ResponseSendPacket=3,//回应发送数据包

ResponseEndPacket=4//数据包传送结束

}

通过这几个指令,我们就可以远程视频了。这是一个这样的过程:

首先接收端请求视频(requestVideoCapital)-->发送端收到并获取摄像头的图片进行分包(ResponseSendPacket),再发送第一个包-->接收端收到包并请求下一个包(requestSendPacket)-->发送端判断是否包尾,如果包尾,就通知客户(ResponseEndPacket)-->接收端判断是否包尾,如果是,就重包,并再请求(requestVideoCapital)形成一个循环的网络传输,这样就是一个视频实时监控了!

下面说说接收端重包的方法:

我们首先定义一个存储包的数组:

 private byte[] imageBuffer;

在重新请求的时候,将 imageBuffer=null;

当收到包的时候:CopyData(data);

 private void CopyData(byte[] data)
        {
            if (imageBuffer == null)
            {
                imageBuffer = data;
                return;
            }
            byte[] buffer = new byte[imageBuffer.Length + data.Length];
            Buffer.BlockCopy(imageBuffer, 0, buffer, 0, imageBuffer.Length);
            Buffer.BlockCopy(data, 0, buffer, imageBuffer.Length, data.Length);
            imageBuffer = buffer;
        }

写了这么多了,还是附上源码才是硬道理:

 http://download.csdn.net/detail/keepmoving0407/5482837

猜你喜欢

转载自blog.csdn.net/keepmoving0407/article/details/8994888