`
yaojialing
  • 浏览: 255840 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Nio 框架 Apache Mina 2 总结(自定义编解码)

阅读更多

认识:

Apache MINA 2 是一个开发高性能和高可伸缩性网络应用程序的网络应用框架。它提供了一个抽象的事件驱动的异步 API,可以使用 TCP/IP、UDP/IP、串口和虚拟机内部的管道等传输方式。Apache MINA 2 可以作为开发网络应用程序的一个良好基础。

 

学习MINA的原因:

由于项目中使用到了socket,并且使用的是传统阻塞式socket编程,项目二期的时候发现生产环境过一段时间就会内存溢出,性能也没有一个好的保证,用检测工具发现线程很多阻塞了。以前公司都没有做过socket程序占大部分的这种项目,对于我们而言也只能网上找资料学习了。前一段时间对IM即时通讯感兴趣就玩了下openfire,听说底层也是mina,当时也不知道MINA是个什么东东,没注意。后来随着我对我们项目框架的思考,发现我们开发人员自己来写socket底层,一来socket这块比较生疏,不容易写好,弄不好哪里没关闭导致什么问题出现都说不定。二来技术人员很容易钻到技术实现这一块来,而不是更多的去关注实现业务。这样非常不好,我在想是否有一种开源框架,帮我们封装好了socket底层,我们只需要用它就可以了呢,找了下,果然有,不过普遍反应mina比较好,而且是非阻塞的(关于阻塞和非阻塞有什么区别,网上有很多资料),所以就选择学习mina 了,之所以学习它是因为想在后期优化项目中现有socket程序。

 

socket io nio认识:

http://aga.iteye.com/blog/206691
http://blog.chinaunix.net/u3/116483/showart_2281635.html


优劣思考:

http://blog.csdn.net/kangojian/archive/2010/07/03/5711027.aspx

 

mina入门:

http://www.ibm.com/developerworks/cn/opensource/os-cn-apmina/

 

 

mina高级认识:

http://www.ibm.com/developerworks/cn/java/j-lo-mina2/index.html

 

源码研究:

http://bbs.cnw.com.cn/viewthread.php?action=printable&tid=211392

 

优化指南:

http://www.tech-q.cn/thread-5135-1-1.html 

 

 

建议:我觉得MINA源码里面自带的例子一定要玩一遍。

 

 

我自己实现的例子介绍(我使用自定义编解码):

 

ProtocolCodecFilter 用来在字节流和消息对象之间互相转换。当该过滤器接收到字节流的时候,需要首先判断消息的边界,然后把表示一条消息的字节提取出来,通过一定的逻辑转换成消息对象,再把消息对象往后传递,交给 I/O 处理器来执行业务逻辑。这个过程称为“解码”。与“解码”对应的是“编码”过程。在“编码”的时候,过滤器接收到的是消息对象,通过与“解码”相反的逻辑,把消息对象转换成字节,并反向传递,交给 I/O 服务来执行 I/O 操作。

在“编码”和“解码”中的一个重要问题是如何在字节流中判断消息的边界。通常来说,有三种办法解决这个问题:

  • 使用固定长度的消息。这种方式实现起来比较简单,只需要每次读取特定数量的字节即可。
  • 使用固定长度的消息头来指明消息主体的长度。比如每个消息开始的 4 个字节的值表示了后面紧跟的消息主体的长度。只需要首先读取该长度,再读取指定数量的字节即可。
  • 使用分隔符。消息之间通过特定模式的分隔符来分隔。每次只要遇到该模式的字节,就表示到了一个消息的末尾。

 

具体到示例应用来说,客户端和服务器之间的通信协议比较复杂,有不同种类的消息。每种消息的格式都不相同,同类消息的内容也不尽相同。因此,使用固定长度的消息头来指明消息主体的长度就成了最好的选择。

 

消息头

4个字节

消息体

不定长度

 

 

mina编解码流程:request->MyDecoder->MyHandler->MyEncode->response

 

---------------------自定义编解码代码实现----------------------------

 

解码:MyProtocalDecoder.java

 

package com.ccic.mina.myprotocal;

import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.AttributeKey;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;

public class MyProtocalDecoder implements ProtocolDecoder {
	private final AttributeKey CONTEXT = new AttributeKey(getClass(), "context");
	private final Charset charset;
	private int maxPackLength = 4000;

	public MyProtocalDecoder() {
		this(Charset.defaultCharset());
	}

	public MyProtocalDecoder(Charset charset) {
		this.charset = charset;
	}

	public int getMaxLineLength() {
		return maxPackLength;
	}

	public void setMaxLineLength(int maxLineLength) {
		if (maxLineLength <= 0) {
			throw new IllegalArgumentException("maxLineLength: " + maxLineLength);
		}
		this.maxPackLength = maxLineLength;
	}

	private Context getContext(IoSession session) {
		Context ctx;
		ctx = (Context) session.getAttribute(CONTEXT);
		if (ctx == null) {
			ctx = new Context();
			session.setAttribute(CONTEXT, ctx);
		}
		return ctx;
	}

	public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
		final int packHeadLength = 8;
		// 先获取上次的处理上下文,其中可能有未处理完的数据
		Context ctx = getContext(session);
		// 先把当前buffer中的数据追加到Context的buffer当中
		ctx.append(in);
		// 把position指向0位置,把limit指向原来的position位置
		IoBuffer buf = ctx.getBuffer();
		buf.flip();
		// 然后按数据包的协议进行读取
		while (buf.remaining() >= packHeadLength) {
			buf.mark();
			// 读取消息头部分
			int length = buf.getInt();

			// 检查读取是否正常,不正常的话清空buffer
			if (length < 0 || length > maxPackLength) {
				System.out.println("长度[" + length + "] > maxPackLength or <0....");
				buf.clear();
				break;
			}
			// 读取正常的消息,并写入输出流中,以便IoHandler进行处理
			else if (length >= packHeadLength && length - packHeadLength <= buf.remaining()) {
				int oldLimit2 = buf.limit();
				buf.limit(buf.position() + length - packHeadLength);
				String content = buf.getString(ctx.getDecoder());
				buf.limit(oldLimit2);
				out.write(content);
			} else {
				// 如果消息包不完整
				// 将指针重新移动消息头的起始位置
				buf.reset();
				break;
			}
		}
		if (buf.hasRemaining()) {
			// 将数据移到buffer的最前面
			IoBuffer temp = IoBuffer.allocate(maxPackLength).setAutoExpand(true);
			temp.put(buf);
			temp.flip();
			buf.clear();
			buf.put(temp);

		} else {// 如果数据已经处理完毕,进行清空
			buf.clear();
		}
	}

	public void finishDecode(IoSession session, ProtocolDecoderOutput out) throws Exception {
	}

	public void dispose(IoSession session) throws Exception {
		Context ctx = (Context) session.getAttribute(CONTEXT);
		if (ctx != null) {
			session.removeAttribute(CONTEXT);
		}
	}

	// 记录上下文,因为数据触发没有规模,很可能只收到数据包的一半
	// 所以,需要上下文拼起来才能完整的处理
	private class Context {
		private final CharsetDecoder decoder;
		private IoBuffer buf;
		private int matchCount = 0;
		private int overflowPosition = 0;

		private Context() {
			decoder = charset.newDecoder();
			buf = IoBuffer.allocate(3000).setAutoExpand(true);
		}

		public CharsetDecoder getDecoder() {
			return decoder;
		}

		public IoBuffer getBuffer() {
			return buf;
		}

		public int getOverflowPosition() {
			return overflowPosition;
		}

		public int getMatchCount() {
			return matchCount;
		}

		public void setMatchCount(int matchCount) {
			this.matchCount = matchCount;
		}

		public void reset() {
			overflowPosition = 0;
			matchCount = 0;
			decoder.reset();
		}

		public void append(IoBuffer in) {
			getBuffer().put(in);

		}

	}
}

 

 

编码:MyProtocalEncoder.java

 

package com.ccic.mina.myprotocal;

import java.nio.charset.Charset;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;

public class MyProtocalEncoder extends ProtocolEncoderAdapter {
	private final Charset charset;

	public MyProtocalEncoder(Charset charset) {
		this.charset = charset;
	}

	// 在此处实现包的编码工作,并把它写入输出流中
	public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
		String value = (String) message;
		IoBuffer buf = IoBuffer.allocate(value.getBytes().length);
		buf.setAutoExpand(true);
		if (value != null)
			buf.put(value.trim().getBytes());
		buf.flip();
		out.write(buf);
	}

	
}

 编解码工厂类:MyProtocalCodecFactory.java

 

package com.ccic.mina.myprotocal;

import java.nio.charset.Charset;

import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolEncoder;

public class MyProtocalCodecFactory implements ProtocolCodecFactory {
	private final MyProtocalEncoder encoder;
	private final MyProtocalDecoder decoder;

	public MyProtocalCodecFactory(Charset charset) {
		encoder = new MyProtocalEncoder(charset);
		decoder = new MyProtocalDecoder(charset);
	}

	public ProtocolEncoder getEncoder(IoSession session) {
		return encoder;
	}

	public ProtocolDecoder getDecoder(IoSession session) {
		return decoder;
	}

}

 

 

Handler类:MyHandler.java

package com.ccic.mina.myprotocal;

import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

class MyHandler extends IoHandlerAdapter {
	private final static Logger LOGGER = LoggerFactory.getLogger(MyHandler.class);

	@Override
	public void sessionOpened(IoSession session) throws Exception {
		LOGGER.info(" session is Opened..." + session.getId());
	}

	@Override
	public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
		// log.warn(" cause.getMessage()..." + cause.printStackTrace());
		session.close(true);
	}

	@Override
	public void messageReceived(IoSession session, Object message) throws Exception {
		String pack = (String) message;

		// 接收报文,进行业务处理

		// 返回报文给客户端
		session.write(pack);
	}

	@Override
	public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
		LOGGER.info("IDLE " + session.getIdleCount(status));
	}
}

 

 

 

 

客户端: MyProtocalClient.java

 

package com.ccic.mina.myprotocal;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.Socket;

public class MyProtocalClient {
	// mina编解码流程:request->MyDecoder->MyHandler->MyEncode->response
	// 对于长度>1000字节的数据包采用分段发送。
	public static void main(String[] args) {
		try {
			Socket socket = new Socket("127.0.0.1", 8080);
			DataOutputStream out = new DataOutputStream(socket.getOutputStream());
			InputStreamReader inputStreamReader = new InputStreamReader(socket.getInputStream());
			BufferedReader in = new BufferedReader(inputStreamReader);
			for (int i = 0; i < 200; i++) {
				long startTime = System.currentTimeMillis(); // 获取开始时间
				String str = "2BC0A039329D8FF6F4CB8BAA71A45FED8E119BEB76F0F1B1AA99F73B867C1685AF0F903F10F65505A4D618E30C0A1A9046FF3301A368AD36A7ADC78761E6C4C758D2611F3F3E3C448E63CE1B2CA88ACF7C54F44AC3621D927C16E5C4876FFDF51392FF7BFE8392420B6125504F53AB5C5CB1C350EA67BE577B6DB689F63C47B5F5593C55B607667240A57DF820109A13194C42AA1F3205771AB9E3C359555BC973FF59DD752E19CB472B61D8FA910A0C820A2677A2032723A00E87079F0A79BB9ACA930EBF7F25BC31AA7E1DA70810FC2ABA508269185FC6306082E966D82464CBF07B77502962EE378629C74B26BD3B536CDAA049D3841B36B7B7A4E9EC95CDE330ABFCD594DF4FAE3DEEB99DBC8DDA054F4D6B0F0EAEE82A21771A92635CAD9FFE021A2A408BC7C40060CCA98C77FEB8A7F5BC8AD5A64CF58BC0D5C9ED56D1E2450A2A674E53093BC015E2CEFC1D9B6B8BC79B85868C47586632DDEA08ED9EEE31A4DC9D777C28AD65892E1C5E1260AFF9299E162FE3276CF1A0FAD89878FF89ACEFF48C2B0FCD07E272C834F0C07C1838A39F019D1184232688F40AC0AE2F302B8F20A12F7D7511042E7B68E0C07D3B94CC61609097B9B7062B9DEE91E73DCDD268CBD247DB2348311A4EC1A7CAA554287C464F751960624236313976D16B5C735F1083FD18CC1FB56614A3B9B7F32249A38FD1A6EF235369E2311D6C964F2D459C75EA732BD1F3095BB2DA5821655974E1A53E5EBDA47652000D563F52A48CA00F395EDAEC58EEBE8D46C57886F8C5811E6C8F5A979DE911249F07370FB8BEF8BB35E0E64608EC43581DFBFEABE6C11337FD05DCBDC9242EBFD42D82DD59D72682D3C94945FEB03051153863CD3556E6B87BABCF1A5B01698D459FD01CFB7C28C650E0A8FE575C8E380601D55E517DF5852F07A49CF982635FA1E4689AF1D9B94F02D8F00B4AED356401FF6FFC1FC73C99D3025C08096FEF6659F32EA4D53279FAC697D56339F1A5F689E806F0F900A09A8F4CDB64B5DACEF7D6DC06460217234794DB61CC5AD6E8534B4BA5FB3B38B8D195E3B71AEBA4983606E00ECDC644CFFC5696140C78767139B3806C68F4906810030BC23DFE91C1C8CD11F758CCB3E4BCFD254B5D3959EC7F7764CE76DB74E117E7F844ADA94F99B02AC961A87C3084358D6B64540898788BDAA8455F374B607C7ACAB489BE099AB7C7AD78EFF8C1405A90DDAF23EB5D454167178620458227922B8A8E9E1D8D980089FBFC8143BA8FFD96E49A18C32BAEFB088956A75192805D44C5C2BFB345D6FA54A74C8B8B6BD566F24DB3BAB58F71BDB03807A566DEFCAC57889F2CE4803B39D64AF61291D3C56A5C0B4F3C3E287CAD8540505E23A24EA2D4815A742ED7F9173F8C157735B8D7FA20727E013E5BEECEF3DAC27960E7BA025D5335952AC1C0CBB94523835574FCB1E5B5E1782FC1EFA9B0471F3D443F6104C13698929D2FCE5B2220BF9DCD125CA8F8918826A48F960CEE66E01AB5F066630E1793277838E0F997D8C8A01C086387BB2718C7CA1A1C3BB46223CE0B367DD86DCA768D50F41BB40188709103D2C854044DE2653002EEB78965D8141B5A6900B17A94A6846CA2595436E45DA841F6DC3165187DAF6499DB5B15233A7205D9CB70D8776F109C6B744A0DA3ADC4EABEFA6C83C28BC2BC4C3389CF792F1AC9B544290D1A5C0CCBD69E89183A08A5B2496398358A6005FD404EF89678BE00FA0034C192D5B089A92083F93C5E8A8E36367A9DA75B463A6566806FACB47E71C4276F45D294CE54E7292DBD092E8D6D74C474D49D94BA5594090EDD12AC06DE72DDEC2AB56AD94C";
				String temp_ = "";
				int SUB_COUNT = 1000;// 按1000个字节来截取字符串
				// 发送数据包长度
				out.writeInt(2608 + 8);
				// 分段来发送数据
				for (int c = 0; c < str.getBytes().length / SUB_COUNT; c++) {
					if (temp_ == "" && temp_.length() == 0) {
						temp_ = str.substring(c * SUB_COUNT, SUB_COUNT);
						// 发送第一次也是第一段数据
						out.write(temp_.getBytes());
					} else {
						// 按1000个字节分段发送数据
						out.write(str.substring(c * SUB_COUNT, (c + 1) * SUB_COUNT).getBytes());

						// 发送剩余的不足1000个字节的数据串
						int raim_ = str.substring((c + 1) * SUB_COUNT, str.getBytes().length).length();
						if (raim_ < SUB_COUNT && raim_ != 0) {
							out.write(str.substring((c + 1) * SUB_COUNT, str.getBytes().length).getBytes());
						}
					}
				}
				// 马上写入,释放缓存
				out.flush();
				System.out.println(i + " sended");

				char temp[] = new char[2700];
				String backLine = "";
				in.read(temp);
				backLine = String.valueOf(temp).trim();
				System.out.println("backLine==" + backLine);
				long endTime = System.currentTimeMillis(); // 获取结束时间
				System.out.println("程序运行时间(毫秒): " + (endTime - startTime) + "ms");
			}
			Thread.sleep(1000);
			out.close();
			in.close();
			socket.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

 

 

 

服务端类:MyProtocalServer.java

 

package com.ccic.mina.myprotocal;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.concurrent.Executors;

import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.executor.ExecutorFilter;
import org.apache.mina.filter.logging.LogLevel;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

/**
 * mina编解码流程:request->MyDecoder->MyHandler->MyEncode->response
 * 
 * @author
 * 
 */
public class MyProtocalServer {
	private static final int PORT = 8080;

	// static Logger logger = Logger.getLogger(MyProtocalServer.class);

	public static void main(String[] args) throws IOException {
		// PropertyConfigurator.configure("conf\\log4j.properties");
		IoAcceptor acceptor = new NioSocketAcceptor();
		// Log4jFilter lf = new Log4jFilter(logger);

		// 定义SLF4J 日志级别 Look: http://riddickbryant.iteye.com/blog/564330
		LoggingFilter loggingFilter = new LoggingFilter();
		loggingFilter.setSessionCreatedLogLevel(LogLevel.NONE);// 一个新的session被创建时触发
		loggingFilter.setSessionOpenedLogLevel(LogLevel.NONE);// 一个新的session打开时触发
		loggingFilter.setSessionClosedLogLevel(LogLevel.NONE);// 一个session被关闭时触发
		loggingFilter.setMessageReceivedLogLevel(LogLevel.NONE);// 接收到数据时触发
		loggingFilter.setMessageSentLogLevel(LogLevel.NONE);// 数据被发送后触发
		loggingFilter.setSessionIdleLogLevel(LogLevel.INFO);// 一个session空闲了一定时间后触发
		loggingFilter.setExceptionCaughtLogLevel(LogLevel.INFO);// 当有异常抛出时触发

		acceptor.getFilterChain().addLast("logger", loggingFilter);
		// 过滤器(自定义协议)
		acceptor.getFilterChain().addLast("codec",
				new ProtocolCodecFilter(new MyProtocalCodecFactory(Charset.forName("UTF-8"))));
		// 设置数据将被读取的缓冲区大小
		acceptor.getSessionConfig().setReadBufferSize(3000);
		// 10秒内没有读写就设置为空闲通道
		acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);

		// 连接池设置
		// get a reference to the filter chain from the acceptor
		DefaultIoFilterChainBuilder filterChainBuilder = acceptor.getFilterChain();
		filterChainBuilder.addLast("threadPool", new ExecutorFilter(Executors.newCachedThreadPool()));

		acceptor.setHandler(new MyHandler());
		acceptor.bind(new InetSocketAddress(PORT));
		System.out.println("Start server is listenig at port " + PORT);
	}
}

 

 

运行:

启动服务端server: MyProtocalServer->Main方法

客户端:MyProtocalClient->Main方法

 

 

注意:我的消息体长度有两千多个字节,如果一次性write的话,处理返回会需要六七秒,这是因为如果发送消息体过大会自动断包,decoder这里会分段读取好几次,就在这里花费了一定的时间。

只需要客户端把这种比较长的消息体分段发送就可以了,最好每次out.wirte不要超过1000byte。分段后速度就快很多了。

分享到:
评论
9 楼 baso4233 2012-12-26  
学习了。可能会用到。
8 楼 sunjunliangsunjun 2012-06-19  
谢谢  博主的总结!   端午节 学了 
7 楼 george6684 2011-12-23  
final int packHeadLength = 8;
消息头 是 int的话  这里不该是 4吗?
我改成4 也能跑通。。
是因为别的原因这里要写8吗?
6 楼 chenyongxin 2011-10-28  
mark.
5 楼 yaojialing 2011-10-17  
Pelephone 写道
有个问题,有中文字符会出错...丢包..


有无搞错,你发送包不经过转码加密的吗?
4 楼 yaojialing 2011-10-17  
maozilee 写道
如果协议后面有个 “消息尾”   是不是DECODE就简单多了呢??

定义包有三种:定长、结尾标识符、报文头报文体。看你需求了,呵呵
3 楼 Pelephone 2011-09-23  
有个问题,有中文字符会出错...丢包..
2 楼 maozilee 2011-08-27  
如果协议后面有个 “消息尾”   是不是DECODE就简单多了呢??
1 楼 maozilee 2011-08-25  
兄弟,你写的很好!网上MINA的自定义不是很多,高手总是能写的简单易懂啊!!

相关推荐

    apache-mina-2.0.4.rar_apache mina_mina

    Apache Mina是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。这个"apache-mina-2.0.4.rar"压缩包包含的是Apache Mina 2.0.4版本的源代码,是深入理解和定制Mina的...

    Apache mina2学习笔记DEMO

    在这个"Apache MINA2学习笔记DEMO"中,我们很可能会看到如何使用MINA来创建一个自定义协议的示例。自定义协议通常是为了满足特定应用的需求,例如高效的数据传输、安全性或者特定的编码格式。MINA允许开发者定义自己...

    Apache Mina帮助文档

    Apache Mina是一个高度可扩展的网络通信框架,主要用于构建高性能、高效率的服务端应用程序。它提供了事件驱动、异步I/O处理模型,使得开发者能够更专注于业务逻辑,而不是底层网络编程的复杂性。Mina主要应用于Java...

    apache Mina的完整学习资料

    Apache Mina是一个开源框架,主要用于构建高性能、高可用性的网络应用程序。这个压缩包包含了全面的学习资料,适合初学者深入理解Mina的原理和使用方法。其中,中文参考手册的加入使得学习过程更加友好,便于非英语...

    Apache mina框架入门教程

    Apache Mina 框架是一个强大的网络通信应用框架,它主要针对基于TCP/IP和UDP/IP的协议栈,同时也支持Java对象序列化和其他通信方式。Mina 的核心设计目标是帮助开发者快速构建高性能、高可扩展性的网络应用。它采用...

    Apache mina源代码框架解析

    Apache Mina是一个用Java编写的网络通信框架,它简化了创建高性能、高可用性的网络服务的过程。Mina的核心思想是提供一个与传输层协议无关的API,使得开发者可以专注于业务逻辑,而不需要关心底层的网络通信细节。在...

    niosocket及其开源框架MINA学习总结收集.pdf

    MINA (Java Multithreaded Network Application Framework) 是一个基于NIO的开源框架,它为开发高性能、高可用性的网络应用提供了抽象层。MINA 提供了事件驱动的模型,简化了网络编程的复杂性,开发者可以通过编写...

    Apache_Mina2.0学习笔记

    最近使用Mina开发一个Java的NIO服务端程序,因此也特意学习了Apache的这个Mina框架。 引言 1 一. Mina入门 2 第一步.下载使用的Jar包 2 第二步.工程创建配置 2 第三步.服务端程序 3 第四步.客户端程序 6 第五步.长...

    Apache MINA 2.0 用户指南( 缺第一章节)

    Apache MINA 2.0 是一款高性能且易于使用的网络应用程序框架,它简化了开发人员在网络编程方面的负担,允许开发者专注于应用程序的核心功能,而不是底层的网络细节。MINA 2.0 支持多种网络协议,包括 TCP 和 UDP,...

    Apache Mina Server 2.0 抢鲜体验

    Apache Mina Server 2.0 是一款高性能、可扩展的网络通信框架,广泛应用于开发网络应用服务器,如TCP/IP和UDP服务。这个框架允许开发者用Java编写高效的网络应用程序,简化了网络编程的复杂性。Mina 2.0 版本在前一...

    apache-mina源码

    6. **Protocol Buffers**:MINA提供了协议编解码机制,允许开发者自定义协议格式。这使得MINA能灵活地支持各种网络协议,如HTTP、FTP、SMTP等。 在`apache-mina-2.0.16`这个版本中,我们可以看到以下主要内容: - ...

    apache mina-spring 服务端程序

    Apache Mina是一个高度可扩展的网络通信框架,主要用于构建高性能、高并发的网络应用程序,如服务器端应用。它提供了一种简单而强大的编程模型,使得开发者可以专注于业务逻辑,而不是底层的网络通信细节。Spring...

    mina2核心框架

    MINA(Java Multithreaded Network Application Framework)是一个由Apache软件基金会开发的开源网络通信框架,主要应用于构建高性能、高可用性的网络服务。MINA2作为其最新版本,尤其在处理大量并发连接时展现出了...

    Apache MINA基于JAVA的网络服务器框架 教程.zip

    3. **过滤器架构**:MINA的过滤器链允许开发者插入自定义的过滤器,对数据进行预处理或后处理,例如数据编码、解码、安全加密等。 4. **跨平台兼容**:由于MINA是用Java编写的,因此它可以运行在任何支持Java的平台...

    Apache MINA 线程模型配置

    Apache MINA 是一个用于构建网络应用程序的高性能、高可靠性的框架。它提供了丰富的功能来简化网络编程,包括TCP/IP 和 UDP/IP 协议的支持。线程模型是 MINA 的核心组成部分之一,负责管理 I/O 操作中的线程分配与...

    apache mina

    Mina 2.0.16 简介 代码实例 Mina 是Apache开发的一个开源的网络通信框架,基于java NIO实现。 建立server与client之间的会话连接,对会话消息进行过滤; 非阻塞消息会话机制; 通过自定义的通信协议进行编解码消息。

    Apache_MINA_2_用户指南.pdf

    Apache MINA 2 是一个基于 Java 语言的网络应用框架,旨在帮助开发者快速构建高性能、可靠、可扩展的网络应用程序。该框架提供了一个灵活的架构,使得开发者可以轻松地构建各种类型的网络应用程序。 Part I - ...

    springboot 整合mina 源码,nio通讯基础教程,mina框架基础教程.rar

    Mina框架基于NIO,提供了高级抽象,如IoSession(会话)、ProtocolDecoder(解码器)和ProtocolEncoder(编码器)。这些组件使得我们能够方便地处理网络协议的解析和编码工作,降低了开发复杂性。 在实际的通信过程...

Global site tag (gtag.js) - Google Analytics