首页 新闻 赞助 找找看

C# 如何Socket请求服务端,我不知道按要求组织报文发送数据,

0
悬赏园豆:10 [已解决问题] 解决于 2017-07-05 17:33

上面的是传输报文格式,下面是服务端的一个接口,我要在客户端去进行调用,请问各位大神,该怎么弄?

 

居~的主页 居~ | 初学一级 | 园豆:28
提问于:2017-06-15 16:03
< >
分享
最佳答案
0

参考一下,向服务器发送socket数据流

1.socket连接上,向服务器发送指定格式的报文,将数据进行封包,命令头(1字节)+命令(2字节)+长度(2字节 什么数据的长度)+数据区域+crc32校验码(4字节)

2.按照业务流程进行发送报文,回来的报文数据进行拆包,按照回来的报文的数据格式进行解包。

收获园豆:10
SAI2014 | 菜鸟二级 |园豆:239 | 2017-06-15 16:21

【将数据进行封包,命令头(1字节)+命令(2字节)+长度(2字节 什么数据的长度)+数据区域+crc32校验码(4字节)】 

 

这种使用C#代码怎么写??麻烦写个例子,谢谢。

居~ | 园豆:28 (初学一级) | 2017-06-15 18:03

@久久小垠: http://www.cnblogs.com/huapiaoshuiliuxi/p/4841011.html 如果文件还在的话自己弄来看。

花飘水流兮 | 园豆:13540 (专家六级) | 2017-06-15 20:59

@久久小垠: 这是我之前写的代码 个人理解 你可以参考一下 将要发送的文本或者数据进行封包成byte[] 通过socekt发送到服务端 具体按找你的报文格式进行修改(包头+内容+包尾)返回回来的流按照指定的报文格式进行拆包 得到数据

/// <summary>
/// 包头 0x68, 0x68, 0x16, 0x16
/// </summary>
/// <returns></returns>
public byte[] GetHeader()
{
byte[] header = new byte[4] { 0x68, 0x68, 0x16, 0x16 };
return header;
}

/// <summary>
/// 包尾 0x55, 0xAA, 0x55, 0xAA
/// </summary>
/// <returns></returns>
public byte[] GetEnder()
{
byte[] ender = new byte[4] { 0x55, 0xAA, 0x55, 0xAA };
return ender;
}

/// <summary>
/// 指令序号
/// </summary>
/// <returns></returns>
public static byte[] GetCmd()
{
byte[] cmd = new byte[4] { 0x0, 0x0, 0x0, 0x0 };
return cmd;
}

/// <summary>
/// 封包
/// </summary>
/// <param name="xmlData"></param>
/// <returns></returns>
public byte[] PackData(string xmlData)
{
//aes 加密 OK
string xml = MyAES.AESEncrypt(xmlData);//AES.AESEncrypt(xmlData);
byte[] _Data = Convert.FromBase64String(xml);

byte[] _LengthData = new byte[4];
MessageLength = 4 + _Data.Length;//4为指令序号的长度

_LengthData = BitConverter.GetBytes(MessageLength);

List<byte> _ValiData = new List<byte>();//有效数据
_ValiData.AddRange(GetCmd());
_ValiData.AddRange(_Data);

short crc = (short)CRCHelper.GetValue(_ValiData.ToArray(), 0, _ValiData.Count);
byte[] CRCCode = new byte[2];
CRCCode = BitConverter.GetBytes(crc);

List<byte> _PackData = new List<byte>();//完整包
//组合PackData
_PackData.AddRange(GetHeader());
_PackData.AddRange(_LengthData);
_PackData.AddRange(_ValiData);
_PackData.AddRange(CRCCode);
_PackData.AddRange(GetEnder());
return _PackData.ToArray();
}

SAI2014 | 园豆:239 (菜鸟二级) | 2017-06-16 14:30

@SAI2014: 谢谢,我先看一下

居~ | 园豆:28 (初学一级) | 2017-06-16 14:32

这个已经找到了,谢谢。现在正在搞解包的过程

居~ | 园豆:28 (初学一级) | 2017-06-16 17:30

@SAI2014: 你这个封包的过程很清楚,解包是怎么解的?

居~ | 园豆:28 (初学一级) | 2017-06-16 19:34

@久久小垠: 解包不是就逆向过程吗?根据返回包的信息组成协议进行解析。代码如下 参考一下

/// <summary>
/// 判断两个byte数组是否一致
/// </summary>
/// <param name="soure"></param>
/// <param name="target"></param>
/// <returns></returns>
public static bool IsSame(byte[] soure, byte[] target)
{
bool isSame = true; ;
if (soure.Length == target.Length)
{
for (int i = 0; i < soure.Length; i++)
{
if (soure[i] != target[i])
{
isSame = false;
break;
}
}
}
else
{
isSame = false;
}
return isSame;
}

public string UnPack(byte[] recByte)
{

byte[] header = new byte[4];
byte[] ender = new byte[4];
byte[] lengther = new byte[4];
byte[] cRcCode = new byte[2];

if (recByte.Length <= 4 + 4 + 4 + 2)
{
throw new Exception("网络流长度不正确");
}

Array.Copy(recByte, 0, header, 0, 4);
//不是包头
bool same = IsSame(GetHeader(), header);

if (!same)
{
throw new Exception("报文包头不匹配!");
}
Array.Copy(recByte, 4, lengther, 0, 4);
int validteLength = BitConverter.ToInt32(lengther, 0);
if (recByte.Length != (4 + 4 + validteLength + 2 + 4))
{
throw new Exception("报文长度不匹配");
}
byte[] validateData = new byte[validteLength];
byte[] xmlData = new byte[validteLength - 4];

Array.Copy(recByte, 8, validateData, 0, validteLength);

short crc = (short)CRCHelper.GetValue(validateData, 0, validateData.Length);
byte[] CRCCode = new byte[2];
CRCCode = BitConverter.GetBytes(crc);

Array.Copy(recByte, 8 + validteLength, cRcCode, 0, 2);

//找到CRC
bool crcsame = IsSame(cRcCode, CRCCode);
if (!crcsame)
{
throw new Exception("有效数据长度CRC验证失败!");
}
Array.Copy(validateData, 4, xmlData, 0, validteLength - 4);
string data = Convert.ToBase64String(xmlData);

string xml = MyAES.AESDecrypt(data);//解密得到内容

return xml;
}

SAI2014 | 园豆:239 (菜鸟二级) | 2017-06-19 15:06
其他回答(1)
0

1.socket是传出去一个字节流

2.这个字节流有格式.

3.格式就是1.第一个字节为0x02 2.接着2个字节是命令编号.比如你这个上传证书命令.编码就是0X0700  3.接着2个字节是后面的数据长度,4.然后接着要发送的实际数据字节流.5.crc校验码.这时要问一下.这个校验码包括哪些部分.是前面全部.还是只有数据域

吴瑞祥 | 园豆:29449 (高人七级) | 2017-06-15 16:10

校验码 前面的数据域那一部分

支持(0) 反对(0) 居~ | 园豆:28 (初学一级) | 2017-06-15 16:14

@久久小垠: 然后你的问题是啥.我有点搞不懂.这个图片上写的挺清楚的.

支持(0) 反对(0) 吴瑞祥 | 园豆:29449 (高人七级) | 2017-06-15 16:19

@吴瑞祥: 我不知道怎么写那个组装报文的代码,=_=||

支持(0) 反对(0) 居~ | 园豆:28 (初学一级) | 2017-06-15 17:46

@久久小垠: 意思是不会操作数组?

支持(0) 反对(0) 吴瑞祥 | 园豆:29449 (高人七级) | 2017-06-15 18:23

@吴瑞祥: 不是,我在网上找了些例子,我是直接定义数组还是组装好字符串之后转成Byte数组好一点?

支持(0) 反对(0) 居~ | 园豆:28 (初学一级) | 2017-06-15 18:38

@久久小垠: 你这个情况明显是字节数组啊.不管字符串的事情.

支持(0) 反对(0) 吴瑞祥 | 园豆:29449 (高人七级) | 2017-06-15 20:27

@吴瑞祥: 大神 CRC32 校验位怎么取?

支持(0) 反对(0) 居~ | 园豆:28 (初学一级) | 2017-06-17 16:14
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册