前面我们已经分析了发送给服务器的数据,下面就是我们怎样把这些数据post到服务器了,我们看到对AMF的二进制数据处理(序列化及反序列化)很麻烦,有兴趣的朋友可以使
用FluroineFx
FluroineFx官方网站:http://www.fluorinefx.com/
FluroineFx下载地址:http://www.fluorinefx.com/download.html
FluroineFx在线文档:http://www.fluorinefx.com/docs/fluorine/index.html
但由于我们的应用非常简单,所以使用网上流传的一个模拟AMF Post的类,做了些修改,主要是我们现在
应用的编码为UTF8
class AMFPostData
{
public List<byte> Message;
/// <summary>初始化Message</summary>
public AMFPostData(AMFType amftype, int headers, int bodies)
{
//AMF版本
if (amftype == AMFType.AMF0)
{
Message = new List<byte>(new byte[] { 0x00, 0x00 });
}
else if (amftype == AMFType.AMF3)
{
Message = new List<byte>(new byte[] { 0x00, 0x03 });
}
//header数量
Message.Add(BitConverter.GetBytes(headers)[1]);
Message.Add(BitConverter.GetBytes(headers)[0]);
//body数量
Message.Add(BitConverter.GetBytes(bodies)[1]);
Message.Add(BitConverter.GetBytes(bodies)[0]);
}
/// <summary>添加Target</summary>
public void AddTargetAndResponse(string target, string response)
{
//添加Target长度
Message.Add(BitConverter.GetBytes(target.Length)[1]);
Message.Add(BitConverter.GetBytes(target.Length)[0]);
//添加Target内容
Message.AddRange(Encoding.UTF8.GetBytes(target));
//添加Response长度
Message.Add(BitConverter.GetBytes(response.Length)[1]);
Message.Add(BitConverter.GetBytes(response.Length)[0]);
//添加Response内容
Message.AddRange(Encoding.UTF8.GetBytes(response));
}
/// <summary>添加Body</summary>
/// <param name="length"></param>
/// <param name="Content"></param>
public void AddBody(AMFPostDataBody amfpostdatabody)
{
Message.AddRange(amfpostdatabody.GetLength());
Message.AddRange(amfpostdatabody.Content.ToArray());
}
}
class AMFPostDataBody
{
private byte[] length = new byte[4];
public List<byte> Content = new List<byte>();
/// <summary>初始化Body</summary>
public AMFPostDataBody(DataType datatype, int arraylength)
{
//添加类型标识
Content.Add((byte)datatype);
//数组的话添加长度
if (datatype == DataType.Array)
{
Content.Add(BitConverter.GetBytes(arraylength)[3]);
Content.Add(BitConverter.GetBytes(arraylength)[2]);
Content.Add(BitConverter.GetBytes(arraylength)[1]);
Content.Add(BitConverter.GetBytes(arraylength)[0]);
}
}
public void AddData(DataType datatype, string value)
{
//添加类型标识
Content.Add((byte)datatype);
switch (datatype)
{
case DataType.Number:
AddData(double.Parse(value));
break;
case DataType.String:
AddData(value);
break;
case DataType.Boolean:
AddData(Boolean.Parse(value));
break;
}
}
#region 各种类型处理方法
/// <summary>Boolean</summary>
private void AddData(bool flag)
{
if (flag)
Content.Add(0x01);
else
Content.Add(0x00);
}
/// <summary>String</summary>
private void AddData(string value)
{
//添加长度
Content.Add(BitConverter.GetBytes(Encoding.UTF8.GetBytes(value).Length)[1]);
Content.Add(BitConverter.GetBytes(Encoding.UTF8.GetBytes(value).Length)[0]);
//添加内容
Content.AddRange(Encoding.UTF8.GetBytes(value));
}
/// <summary>Number</summary>
private void AddData(double number)
{
byte[] b = new byte[8];
b = BitConverter.GetBytes(number);
for (int i = 7; i > -1; i--)
{
Content.Add(b[i]);
}
}
#endregion
public byte[] GetLength()
{
length[0] = BitConverter.GetBytes(Content.Count)[3];
length[1] = BitConverter.GetBytes(Content.Count)[2];
length[2] = BitConverter.GetBytes(Content.Count)[1];
length[3] = BitConverter.GetBytes(Content.Count)[0];
return length;
}
}
public enum AMFType
{
AMF0,
AMF3
}
public enum DataType
{
Number = 0,
Boolean = 1,
String = 2,
UntypedObject = 3,
MovieClip = 4,
Null = 5,
Undefined = 6,
ReferencedObject = 7,
MixedArray = 8,
End = 9,
Array = 10,//0x0A
Date = 11,//0x0B
LongString = 12,//0x0C
TypeAsObject = 13,//0x0D
Recordset = 14,//0x0E
Xml = 15,//0x0F
TypedObject = 16,//0x10
AMF3data = 17//0x11
}
根据前文分析结果,我们生成数据的方法如下
public static byte[] GetData(string key, string startdate, string enddate)
{
AMFPostData amfpostdata = new AMFPostData(AMFType.AMF3, 0, 1);
amfpostdata.AddTargetAndResponse("DataAccessor.getIndexes", "/1");
AMFPostDataBody amfpostdatabody = new AMFPostDataBody(DataType.Array, 5);
amfpostdatabody.AddData(DataType.String, key);
amfpostdatabody.AddData(DataType.String, "0");
amfpostdatabody.AddData(DataType.String, "");
amfpostdatabody.AddData(DataType.String, "3e263816946471096c");
amfpostdatabody.AddData(DataType.String, "032512b3ee00d43d7f4fb2151b24d35109d8402579");
amfpostdata.AddBody(amfpostdatabody);
byte[] data = amfpostdata.Message.ToArray();
return data;
}
可以使用以下方法发送数据及得到返回响应的二进制数据
public static byte[] GetFlashData(string gateway, byte[] data)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(gateway);
request.Method = "Post";
request.ContentType = "application/x-amf";
CookieContainer cookie = new CookieContainer();
request.CookieContainer = cookie;
byte[] requestData = data;
request.ContentLength = requestData.Length;
byte[] responseData = null;
try
{
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(requestData, 0, requestData.Length);
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
using (Stream responseStream = response.GetResponseStream())
{
//StreamToBytes是将流转换为二进制字节数组的方法,下文补上
responseData = StreamToBytes(responseStream);
}
}
catch (Exception ex)
{
Console.WriteLine(DateTime.Now.ToString() + "," + ex.Message);
//Log.WriteLine(DateTime.Now.ToString() + "," + ex.Message);
}
return responseData;
}