包stateC#基于Udp的分包传输
工作之余抽点时间出来写写博文,希望对新接触的朋友有帮助。今天在这里和大家一起学习一下包state
因为要远做程摄像头监控,要用到网络数据传输,百度了一下,很多就是基于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
文章结束给大家分享下程序员的一些笑话语录:
那是习惯决定的,一直保持一个习惯是不好的!IE6的用户不习惯多标签,但是最终肯定还是得转到多标签的浏览器。历史(软件UI)的进步(改善)不是以个人意志(习惯)为转移的!
---------------------------------
原创文章 By
包和state
---------------------------------