因為要遠做程攝像頭監控,要用到網絡數據傳輸,百度了一下,很多就是基於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;
}