65.9K
CodeProject 正在变化。 阅读更多。
Home

具有队列和解析字符串网络数据包功能的 Message Manager

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2016年9月12日

CPOL

2分钟阅读

viewsIcon

9519

downloadIcon

239

为字符串类型消息包建议队列和解析方法。

引言

本文介绍了如何高效地管理数据包的排队和解析。第一部分介绍基于 string 的数据包格式,第二部分介绍排队缓冲区,最后一部分介绍消息解析。

背景

我们需要协议才能与自动化系统中的每个设备进行通信。在许多情况下,这些协议由基于 string 或结构的包组成。基于结构的包比基于字符串的包更容易解析其内容,并且可以组成比字符串包更小的包,但是由于基于字符串的包在异构系统之间具有更高的兼容性,因此基于字符串的包经常用于通信系统。因此,本文介绍了一种具有解析和排队功能的字符串消息包管理器。

fifo Image1               fifo Image2

消息格式

我将记录定义为数据包的单位,该记录具有许多字段。

<RECORD_ID FIELD0=VALUE0 FIELD1=VALUE1 ... FIELDn=VALUEn/>

例如,我们可以将基于结构的包改写为基于字符串的包,如下所示

message format Image

基于结构的包 基于字符串的包
struct EQP_Cleaner {
			         char ID[5];
			         RGB color;
			         int part_number;
			         int duration;
			   }
<EQP_CLEANER ID=EQP01 color=RED part_nubmer=80 
 duration=100/>

Using the Code

我认为您只需使用简单的代码,定义消息格式并使用 clear(..)setQsize(..) 进行队列设置,并处理用于 pushMessage(..)popMessage(..) 的数据即可达到目的。

定义

消息包描述了由记录名称和 Field 集组成的记录。记录和字段的结构如下所示

	public class Field {
		public String name;
		public String value;
	}

	public class Record {
		public String name;
		ArrayList<Field> Fields= new ArrayList<Field>();

		public int size() {
			return Fields.size();
		}
	}

函数描述

void setQsize(int size)

设置存储消息包在缓冲区中的最大大小

int size()

获取当前存储在缓冲区中的消息包的数量

void clear()

刷新缓冲区

void addField(Record t, Field f)

向记录添加字段

void addRecord(Record t)

向缓冲区添加记录

Record getRecord(int index)

获取缓冲区中的第 nth 条记录(n:索引)

Record getRecord(String name)

通过 name 关键字获取记录

Field getField(Record t, int index)

获取指定记录 t 中的第 nth 个字段

Field getField(Record t, String name)

通过指定记录 t 中的 name 关键字获取 field

Record deleteMessage(int index)

删除第 nth 条记录

Record deleteMessage(String name)

通过 name 关键字删除记录

Record popMessage()

获取并删除缓冲区中最旧的记录

void pushMessage(String strLine)

在缓冲区中插入记录,此处的记录将通过解析 string 消息来填充。如果当前缓冲区大小大于最大存储大小,则将删除最旧的记录。

实现

pushMessage(..) 同时实现解析和推送 string 消息到缓冲区存储的功能。

	public void pushMessage(String strLine){
		int bracket_start=0;
		if(strLine.isEmpty() == false) {
		    //if current buffer size is bigger than capacity size, 
            //it will be deleted the oldest one.
			if(size() >= mQsize) {
				Record t = tags.get(0);
				t.Fields.clear();
				tags.remove(0);
			}

            //parsing a string message			
			String bracketName=null;
			String bracketValue=null;
			do {
				int start = 0;
				int end = 0;
				start = strLine.indexOf("<", bracket_start);
				if(start<0) break;
				end = strLine.indexOf("/>", start);
				if(end<0) break;
				String tmp = strLine.substring(start+1, end);
				bracket_start = end;

				start = 0;
				end = tmp.indexOf(" ", start);
				if(end<0) continue;
				bracketName = tmp.substring(start, end);
				bracketValue = tmp.substring(end+1, bracket_start-1);
			}while(bracket_start>=0);

            //add record in the buffer
			if(bracketValue!=null)
			{
				String org = bracketValue;
				Record t = new Record();
				t.name = bracketName;

				int index=0;
				while(index < org.length()) {
					Field f= new Field();
					index = getField(org, index, f);

					addField(t,f);
				}
				addRecord(t);
			}
		}
	}

用法

首先,您必须创建 MessageManager 的对象

MessageManager msgManager = new MessageManager();

并通过 pushMessage(..) 填充缓冲区;

msgManager.pushMessage(strMsg);

根据需要,您可以调用 popMessage(..)

record = msgManager.popMessage();

如果您调用了 popMessage,最终您可以获得使用返回记录所需的字段。

field = msgManager.getField(record,index);

当您想要初始化缓冲区时,可以调用 clear()

msgManager.clear();
	public static void main(String[] args) {
		int buffsize = 6;
		MessageManager.Record record=null;
		MessageManager.Field field=null;

		String strMsg1 = "<MsgId1 field0=192.168.0.1 field1=1001 
                           field2=1002 field3=1003 field4=1004/>";
		String strMsg2 = "<MsgId2 field0=192.168.0.2 field1=2001 
                           field2=2002 field3=2003 field4=2004/>";
		String strMsg3 = "<MsgId3 field0=192.168.0.3 field1=3001 
                           field2=3002 field3=3003 field4=3004/>";
		String strMsg4 = "<MsgId4 field0=192.168.0.4 field1=4001 
                           field2=4002 field3=4003 field4=4004/>";
		String strMsg5 = "<MsgId5 field0=192.168.0.5 field1=5001 
                           field2=5002 field3=5003 field4=5004/>";
		String strMsg6 = "<MsgId6 field0=192.168.0.6 field1=6001 
                           field2=6002 field3=6003 field4=6004/>";
		String strMsg7 = "<MsgId7 field0=192.168.0.7 field1=7001 
                           field2=7002 field3=7003 field4=7004/>";
		
		MessageManager msgManager = new MessageManager();
		
		msgManager.clear();
		System.out.println
             ("Add the buffer by strMsg1,strMsg2,...,strMsg5, buffer size:"+buffsize);
		msgManager.setQsize(buffsize);
		msgManager.pushMessage(strMsg1);
		msgManager.pushMessage(strMsg2);
		msgManager.pushMessage(strMsg3);
		msgManager.pushMessage(strMsg4);
		msgManager.pushMessage(strMsg5);
		msgManager.pushMessage(strMsg6);
		msgManager.pushMessage(strMsg7);
		
		System.out.print("Print buffer--------------------------------------");			
		for(int i=0;i < msgManager.size();i++) {
			record = msgManager.getRecord(i);
			System.out.print("\n"+record.name+":");
			for(int j=0;j < record.size();j++) {
				field = msgManager.getField(record,j);
				if(field!=null)
				System.out.print(" ("+field.name+")"+field.value);
			}
		}
		System.out.print("\nPop message-------------------------------------");
		record = msgManager.popMessage();
		System.out.print("\n"+record.name+":");
		for(int k=0;k < record.size();k++) {
			field = msgManager.getField(record,k);
			if(field!=null)
			System.out.print(" ("+field.name+")"+field.value);
		}			
		System.out.print("\nbuffer after pop-------------------------------");
		for(int i=0;i < msgManager.size();i++) {
			record = msgManager.getRecord(i);
			System.out.print("\n"+record.name+":");
			for(int j=0;j < record.size();j++)
			{
				field = msgManager.getField(record,j);
				if(field!=null)
				System.out.print(" ("+field.name+")"+field.value);
			}
		}
		
		System.out.print("\nFind MsgId5 and it's field3---------------------");
		record = msgManager.getRecord("MsgId5");
		if(record!=null) {
			System.out.print("\n"+record.name+":");
			field = msgManager.getField(record,"field3");
		}else{
			System.out.println("\ncannot find record..");
			field = null;
		}
		
		if(field!=null)
			System.out.print(" ("+field.name+")"+field.value);
		else
			System.out.println("\ncannot find field..");
		
		msgManager.deleteMessage("MsgId6");
		
		System.out.print("\nbuffer after Delete MsgId6 Message-------------");
		for(int i=0;i < msgManager.size();i++) {
			record = msgManager.getRecord(i);
			System.out.print("\n"+record.name+":");
			for(int j=0;j < record.size();j++) {
				field = msgManager.getField(record,j);
				if(field!=null)
				System.out.print(" ("+field.name+")"+field.value);
			}
		}	
	}

[结果]

您可以检查如下结果

result Image

我希望您尝试按照以下说明进行编译和运行

compile Image

关注点

我希望您注意在添加消息后立即进行解析和排队。

历史

  • 2016 年 9 月 12 日:初始版本
© . All rights reserved.