TCP通信如何在客户端解析接收服务器返回的数据

ykp1120 2011-06-18 09:36:46
数据传输的格式为:
(电梯编号,楼层,运行方向,门状态,电梯状态)

其中数据以“(”开始,以“)”结束,中间数据内容见代码及说明。
例如:编号为2号的电梯,第2个楼层,在上行,关门,传输时的数据格式为:(02,02,01,04,00)。传送的数据为变化的数据。
...全文
515 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
ykp1120 2011-06-24
  • 打赏
  • 举报
回复
非常感谢
jq_whh 2011-06-24
  • 打赏
  • 举报
回复
还要增加一个判断,datas中每个字符串的长度应该为2
jq_whh 2011-06-24
  • 打赏
  • 举报
回复
我上面的代码应该反提示的字符串替换成真实的数据。

从C#的角度看,7楼的方法要好的多,我这里是在他的基础上增加了一些容错处理。
你协议中说的两个字符,大都说过bit,所以我当作两个字符组成一个字节。
另外只是作为建议,协议中缺少校验,哪怕是一个累加和校验都可以。


string errorCode = null;
string input = "(02,02,01,04,00)";
//var s = input.Trim(); // 在解析数据之前,最好能够保持接收数据的完整性,出现多余字符可以认为错误
try
{
if (input.Length != 16)
errorCode += "接收数据长度错误"; // 保证接收到的数据是符合协议字符长度的
else
{
if (!input.StartsWith("(") || !input.EndsWith(")"))
throw new Exception("数据的开始或者结束符号格式错误。");

var mid = input.Substring(1, input.Length - 2);
var datas = mid.Split(',');

if (datas.Length != 5)
errorCode += "数据格式错误\n";

int LiftNumber = int.Parse(datas[0]); // 这里用根据实际情况设置
if (LiftNumber < 2/*"最小电梯编号"*/ || LiftNumber > 4/*"最大电梯编号"*/) // 保证不会出现电梯编号数据超范围
errorCode += "电梯号错误\n";

int FloorNumber = int.Parse(datas[1]); // 这里用根据实际情况设置
if (FloorNumber < 5/*"最小楼层编号"*/ || FloorNumber > 12/*"最大楼层编号"*/) // 保证不会出现楼层编号数据超范围
errorCode += "楼层号错误\n";

int Direction = int.Parse(datas[2]);
if (Direction != 1 && Direction != 0) // 保证不会出现方向标志错误
errorCode += "方向标志错误\n";

int DoorStatus = int.Parse(datas[3]); // 这里用根据实际情况设置
if (DoorStatus != 0x01/*"开门状态标志"*/ && DoorStatus > 0x02/*"关门状态标志"*/) // 保证不会出现状态标志错误
errorCode += "门状态标志错误\n";

int LiftStatus = int.Parse(datas[4]);
}
}
catch
{
errorCode += "解析数据错误\n";
}
if (errorCode == null)
errorCode = "数据解析完毕";
MessageBox.Show(errorCode);
ykp1120 2011-06-24
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 jq_whh 的回复:]
显示的是什么错误啊?

再有,我给你写的只是一个范例,提供一个思路,好象字节没有完全对应,for循环中的i就是byte数组的索引,你适当调整一下。

争取自己完成修改吧,还有问题的话,贴一个真实的数据,我再帮你修改一下。
[/Quote]
整个要解析的数据传输格式为:在首次建立TCP/IP连接时,传送所有电梯的当前状态数据,在此后,只是当电梯状态发生改变时才再次上传电梯数据。

数据传输的格式为:
(电梯编号,楼层,运行方向,门状态,电梯状态)

其中数据以“(”开始,以“)”结束,中间数据内容见代码及说明。
例如:编号为2号的电梯,第2个楼层,在上行,关门,传输时的数据格式为:(02,02,01,04,00)。传送的数据为变化的数据。

代码及说明:
1. 电梯编号
编号为二个字符
例如编号为1的电梯,数据的格式为01
13505715554 李民
2. 楼层
楼层为二个字符
例如在第2个楼层,数据格式为02

3.运行方向
运行状态为二个字符
上行:bit0 电梯上行01
下行:bit1 电梯下行02
无运行:00
例如电梯上行,数据的格式01

4.门状态
门状态为二个字符
开门:bit0 01
关门:bit2 02

5. 电梯状态
电梯状态为二个字符
正常: 00 普通运行方式
检修: bit0 01
锁梯: bit1 02
消防/火警:bit2 04
司机: bit3 08
正常供电:bit4 10
紧急供电:bit5 20
急停: bit6 40
故障: bit7 80

例如电梯故障后,数据的格式为80
在客户端接收服务器返回的信息后将数据解析,例如:(02,02,01,04,00)解析为编号为2号的电梯,第2个楼层,在上行,关门,按你说的方法去写,出现这样的错误:运算符“>=”无法运用于string或者string类型的操作数
jq_whh 2011-06-24
  • 打赏
  • 举报
回复
显示的是什么错误啊?

再有,我给你写的只是一个范例,提供一个思路,好象字节没有完全对应,for循环中的i就是byte数组的索引,你适当调整一下。

争取自己完成修改吧,还有问题的话,贴一个真实的数据,我再帮你修改一下。
ykp1120 2011-06-24
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 jq_whh 的回复:]
下面的代码不一定好,可用,只作学习参考


C# code

string errorCode;
byte[] buffer;
int bytes = socket.Receive(buffer);
if (bytes != 7)
errorCode =……
[/Quote]
这样解析不了啊,显示错误
ykp1120 2011-06-19
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 fengyarongaa 的回复:]
先接收

至于解析就看你的数据想要什么格式的

解析的时候做什么操作

说不定
[/Quote]
接收的数据按ASCILL码得格式
ycproc 2011-06-19
  • 打赏
  • 举报
回复
先接收

至于解析就看你的数据想要什么格式的

解析的时候做什么操作

说不定
bruce128 2011-06-18
  • 打赏
  • 举报
回复
用C#的split函数将传输过来的数据拆分成一个字符串数组,split函数的参数用(,),和,三个符号就可以了
  • 打赏
  • 举报
回复
注意,按照你的数据例子,我假设括号和逗号都是中文字的,而不是英文的符号。
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 ykp1120 的回复:]
我也想到了用Split函数分解之后再解析,但不知道具体该怎么去做
[/Quote]
说实在的,这个问出来会让人抓狂的。好吧,给你写个demo:
using System;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string input = "(02,02,01,04,00)";
var s = input.Trim();
if (!s.StartsWith("(") || !s.EndsWith(")"))
throw new Exception("数据的开始或者结束符号格式错误。");

var mid = s.Substring(1, s.Length - 2);
var datas = mid.Split(',');
Console.WriteLine("f1={0}, f2={1}, f3={2}, f4={3}, f5={4}", datas[0], datas[1], datas[2], datas[3], datas[4]);
Console.ReadKey();
}
}
}

对于“split怎么使用”这类问题,最好在实际开发中不再去问别人。自己查。开发中你应该去问跟设计有关的问题,有效沟通。而花时间沟通这类问题,会让高级程序员再也不跟你讨论软件设计问题了。
xuexiaodong2009 2011-06-18
  • 打赏
  • 举报
回复
建议在每条命令后添加换行符,这样在客户端可以一行一行的读,处理就简单多了
需要注意的是服务端和客户端的编码方式一定要对应的,否则就会解析错误的
ykp1120 2011-06-18
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 sp1234 的回复:]
去掉开头的(字符,再去掉结尾的)字符,然后使用字符串的split分解一下,每一个内容就单独装到字符串数组的一个单元中了。如果习惯正则,也可以使用正则(尽管显得有些过度高级)。“按字节查找”则可能是过度低级,忘记了string还有split函数功能的。
[/Quote]
我也想到了用Split函数分解之后再解析,但不知道具体该怎么去做
jq_whh 2011-06-18
  • 打赏
  • 举报
回复
通信协议解析出相应的字段很容易,更重要的容错,一个小小的错误都可能造成致命的后果,还记得许霆恶意取款案吗?看看是怎样因为一个小小的协议错误害了许霆:
http://topic.csdn.net/u/20110617/21/be98d409-c8f7-4853-bee7-9a80647a1c18.html?31680
  • 打赏
  • 举报
回复
去掉开头的(字符,再去掉结尾的)字符,然后使用字符串的split分解一下,每一个内容就单独装到字符串数组的一个单元中了。如果习惯正则,也可以使用正则(尽管显得有些过度高级)。“按字节查找”则可能是过度低级,忘记了string还有split函数功能的。
Alden 2011-06-18
  • 打赏
  • 举报
回复
其实你已经给了数据的规律,如果是这样,只需要按位获取数据即可。
jq_whh 2011-06-18
  • 打赏
  • 举报
回复
下面的代码不一定好,可用,只作学习参考


string errorCode;
byte[] buffer;
int bytes = socket.Receive(buffer);
if (bytes != 7)
errorCode = "非法数据";

for (int i = 0; i < 7; i++)
{
switch (i)
{
case 0:
if (buffer[i] == '(')
MessageBox.Show("开始标志正确");
else
errorCode = "开始标志错误";
break;
case 1:
if (buffer[i] >= "最小电梯编号" && buffer[i] <= "最大电梯编号")
MessageBox.Show("电梯号:" + i.ToString());
else
errorCode = "电梯号错误";
break;
case 2:
if (buffer[i] >= "最低楼层号" && buffer[i] <= "最高楼层号")
MessageBox.Show("楼层号:" + i.ToString());
else
errorCode = "楼层号错误";
break;
//.....// 自己补齐吧
default:
errorCode = "解析过程错误";
break;
}
}

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧