使用mina解析http协议的使用

在使用mina的过程中,我们通常会自定义各种报文,以使用于自己的业务。今天就为大家带来一款类似http协议的解码过程。
mina有自带的解析http数据包的解码类。可以使用maven配置一下内容获取源码:
<dependency>
    <groupId>org.apache.mina</groupId>
    <artifactId>mina-http</artifactId>
    <version>3.0.0-M2</version>
</dependency>
或者下载mina的源码包,查看org.apache.mina.http.HttpServerDecoder类。下面为自己写的解析方法:
package com.server;

import java.lang.reflect.Method;
import java.nio.charset.Charset;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.apache.mina.filter.codec.textline.LineDelimiter;

/**
 * 解码HTTP协议类
 * @author Herman.xiong
 * @date 2015年7月16日09:36:59
 * @version V3.0
 * @since Tomcat6.0,Jdk1.6
 * @copyright Copyright (c) 2015
 */
public class HttpServerDecoder extends CumulativeProtocolDecoder {
	private static final Logger log = Logger.getLogger(HttpServerDecoder.class);

	private LineDelimiter codecLineDelimiter = null;
	private Charset charset = null;
	private static final String MessageLength = "MessageLength";

	public HttpServerDecoder(Charset charset, LineDelimiter codecLineDelimiter) {
		this.charset = charset;
		this.codecLineDelimiter = codecLineDelimiter;
	}

	public Charset getCharset() {
		return charset;
	}

	public void setCharset(Charset charset) {
		this.charset = charset;
	}

	public LineDelimiter getCodecLineDelimiter() {
		return codecLineDelimiter;
	}

	public void setCodecLineDelimiter(LineDelimiter codecLineDelimiter) {
		this.codecLineDelimiter = codecLineDelimiter;
	}
	
	public static void main(String [] args){
		IoBuffer buf = IoBuffer.allocate(100).setAutoExpand(true);
		Charset charset = Charset.forName("UTF-8");
		CharsetEncoder ce=charset.newEncoder();
		HttpServerDecoder socket=new HttpServerDecoder(Charset.forName("UTF-8"),LineDelimiter.CRLF);
		try{
			System.out.println("测试数据,测试数据".getBytes(charset).length);
			buf.putString("MessageMethod:UserAction", ce);
			buf.putString(LineDelimiter.CRLF.getValue(), ce);
			buf.putString("MessageType:GET", ce);
			buf.putString(LineDelimiter.CRLF.getValue(), ce);
			buf.putString("Content-Type:text/html; charset=iso-8859-1", ce);
			buf.putString(LineDelimiter.CRLF.getValue(), ce);
			buf.putString("Connection:keep-alive", ce);
			buf.putString(LineDelimiter.CRLF.getValue(), ce);
			buf.putString("Keep-Alive:200", ce);
			buf.putString(LineDelimiter.CRLF.getValue(), ce);			
			buf.putString("CompressType:jzip", ce);
			buf.putString(LineDelimiter.CRLF.getValue(), ce);
			buf.putString("Params:id=1&uid=2&name=3", ce);
			buf.putString(LineDelimiter.CRLF.getValue(), ce);
			buf.putString("accept-ranges:bytes", ce);
			buf.putString(LineDelimiter.CRLF.getValue(), ce);
			buf.putString("DateTime:DateTime", ce);
			buf.putString(LineDelimiter.CRLF.getValue(), ce);
			buf.putString("MessageLength:27", ce);
			buf.putString(LineDelimiter.CRLF.getValue(), ce);
			//body
			buf.putString("测试数据,测试数据", ce);
			buf.putString(LineDelimiter.CRLF.getValue(), ce);
			buf.flip();
			System.out.println("输出的内容为:"+buf.getString(charset.newDecoder()));
			buf.flip();
			socket.doDecode(null,buf,null);
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	
	/**
	 * 数据包解码
	 */
	protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
		Map<String,Object> map = (Map<String,Object>) session.getAttribute("pocket");
		IoBuffer buf = (IoBuffer)session.getAttribute("pocket_state");
		if(null ==buf)
			buf = IoBuffer.allocate(100).setAutoExpand(true).setAutoShrink(true);
		if(null == map)
			map = new HashMap<String,Object>();
		Integer len = 0;
		while (in.hasRemaining()) {
			len = 0;
            byte b = in.get();
            switch (b){
                case '\r':
                    buf.put(b);
                    break;
                case '\n':
                	buf.put(b);
                	buf.flip();
                    String msg=buf.getString(charset.newDecoder());
					String[] arr = msg.split(":");
                    if(StringUtils.isEmpty(map.get("MessageLength"))){
    					if (2 == arr.length && StringUtils.isNotEmpty(arr[0]) && StringUtils.isNotEmpty(arr[1])) {
							map.put(arr[0],arr[1]);
    					} else {
    						log.error("收到的数据包中存在非法内容!");
    					}
    					if(Constant.HUPU_ZERO.equals(map.get("MessageLength"))){
                        	out.write(map);
    						if(in.position()==in.limit()){
    							session.setAttribute("pocket_state", null);
    							session.setAttribute("pocket",null);
    							return true;
    						}
    						map = new HashMap<String,Object>();
    					}
                    }else{
						map.put(StringUtils.isEmpty(map.get("MessageContent"))?msg:map.get("MessageContent")+msg);
						len=((null == map.get("MessageContent")) ? StringUtils.EMPTY : String.valueOf(map.get("MessageContent"))).getBytes(charset).length;
						if(len==Integer.parseInt(map.get("MessageContent"))+2){
							out.write(map);
							if(in.position()==in.limit()){
								session.setAttribute("pocket_state", null);
								session.setAttribute("pocket",null);
								return true;
							}
						}
						map = new HashMap<String,Object>();
					}
					buf.clear();
                    break;
                default:
                	buf.put(b);
            }
        }
		if(StringUtils.isEmpty(map.get("MessageLength")) || len<Integer.parseInt(map.get("MessageLength"))){
			session.setAttribute("pocket",map);
			session.setAttribute("pocket_state", buf);
		}
		return false;
	}
	
}
欢迎大家关注我的博客!如有疑问,请加QQ群:454796847共同学习!
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Java可以通过使用相关的库和工具来解析IEC 104协议。 IEC 104协议是用于远程监控和控制的通信协议,主要应用在电力系统中。Java可以通过使用第三方库,如Apache Mina、Netty等来对IEC 104进行解析。 首先,Java可以使用相关库来建立TCP/IP连接到远程设备,然后通过发送和接收数据来与设备进行通信。这些库提供了相关的API和方法,用于处理数据的读取、写入和解析。 在收到数据后,Java可以使用特定的解析算法来解析IEC 104协议。通过解析IEC 104的数据结构和字段,Java能够对数据进行理解和处理。 IEC 104协议中定义了多个数据类型和功能码,Java可以通过解析这些数据类型和功能码,来确定接收到的数据的类型和用途。例如,Java可以解析监控信息、遥控命令和遥信数据等。 此外,Java还可以使用相关的库和工具来进行数据转换和处理。例如,可以将IEC 104协议中的二进制数据转换为Java中的对象,以便于更方便地处理和操作数据。 总之,通过使用相关的库和工具,Java可以解析IEC 104协议并进行数据处理和转换,从而实现对远程设备的监控和控制。 ### 回答2: Java是一种面向对象的编程语言,有多种的库和框架可以用于解析IEC 104协议。 IEC 104协议是一种用于远程监控和控制系统的通信协议,通常用于监控电力系统。它使用了一种基于帧的传输机制,通过TCP/IP协议进行通信。 在Java中,可以使用诸如Apache Mina、Netty和JIC104等库和框架来解析IEC 104协议。 这些库和框架提供了一种方便的方式来处理IEC 104协议中的数据包和消息。它们通常提供了一套API和工具,以便开发人员可以轻松地解析和处理IEC 104协议中的数据。 使用这些库和框架,可以编写Java代码来监听和处理从IEC 104设备发送的数据。开发人员可以定义处理规则,根据需要提取和解析不同类型的数据。 在解析过程中,可以使用Java的数据结构和算法来分析和处理IEC 104协议中的数据。开发人员可以使用Java的字节操作函数来提取和转换协议中的各个字段和数值。 通过使用Java解析IEC 104协议,开发人员可以轻松地实现与电力系统的通信,并提取所需的数据以进行进一步的处理和分析。同时,由于Java是一种跨平台的语言,因此可以在多种设备和操作系统上运行和使用这些解析工具。 ### 回答3: Java解析IEC 104协议需要进行以下步骤: 1. 导入相关依赖:使用Java语言编写程序时,首先需要导入相关的库或依赖项。在解析IEC 104协议时,可以使用第三方库,例如Apache MINA或Netty等来简化开发过程。 2. 建立TCP连接:通过Java的Socket类可以建立与IEC 104服务器的TCP连接。使用服务器的IP地址和端口号作为参数,创建一个Socket对象。这将建立客户端与服务器之间的通信通道。 3. 发送读/写命令:根据IEC 104协议的规范,使用Java的OutputStream类向服务器发送读或写命令。这些命令用于请求或更新远程设备的数据。 4. 接收响应数据:通过Java的InputStream类从服务器接收响应数据。根据IEC 104协议的规范,解析服务器发送的数据包。这些数据包可能包含有关设备状态,测量值和遥控点等信息。 5. 解析数据:根据IEC 104协议规范,解析接收到的数据包。这涉及到解析不同数据类型、标记以及可能需要的错误检查等。 6. 处理数据:根据应用程序的需求,使用Java代码处理解析后的数据。例如,将测量值显示在用户界面上,检查设备的状态或根据数据触发其他操作。 7. 关闭连接:在完成所有操作后,使用Java的Socket类关闭与IEC 104服务器的连接。这将释放资源并确保不再使用该连接。 需要注意的是,解析IEC 104协议的具体实现可能会受到所采用的库或框架的影响。上述步骤提供了一个基本的框架,但具体的代码实现可能因库的不同而有所差异。因此,在实际开发中,根据所选的库和协议规范,可能需要进一步查阅相关文档或示例代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

业余草

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值