学习mina同步与异步网络通讯(二)——服务器端

本文介绍如何使用MINA框架设计并实现一个简单的服务器端应用程序。重点讲解服务器端核心组件IoAcceptor和IoHandler的使用,以及消息处理流程、线程模型等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写个服务器端,做测试。

服务器端与客户端最大的区别是使用IoAcceptor和IoHandler

核心代码:

package com.lele.test.mina.server.acceptor;

import java.io.IOException;
import java.net.InetSocketAddress;

import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.SocketAcceptor;
import org.apache.mina.transport.socket.SocketSessionConfig;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

import com.lele.test.mina.server.acceptor.codec.CodecFactory;
import com.lele.test.mina.server.acceptor.handle.MinaServerHandler;

public class MinaAcceptor{

	private int port = 1234;

	// socket接收器
	private SocketAcceptor acceptor;
	private static MinaAcceptor minaAcceptor;
	private SocketSessionConfig sessionConfig;
	//单例模式
	public static  MinaAcceptor getInstances(){
		if (null == minaAcceptor) {                 
			minaAcceptor = new MinaAcceptor();      
        	}              
        	return minaAcceptor;    
	}
	protected MinaAcceptor() {
		acceptor = new NioSocketAcceptor();
		//此处的过滤器与客户端代码一样,使用自定义的CodecFactory
		acceptor.getFilterChain().addLast("codec",
				new ProtocolCodecFilter(new CodecFactory(false)));
		acceptor.getFilterChain().addLast("logger", new LoggingFilter());
		sessionConfig = getAcceptor().getSessionConfig();
		// 设置IoSession的read()方法为可用,默认为false,这行可以去掉,服务器端的read是被封装的,不需要定义IoSession,也不涉及到read(),应该是accptor内部实现了。
		sessionConfig.setUseReadOperation(true);
		//设置处理器
		acceptor.setHandler(new MinaServerHandler());
		try {
			//注册端口。
			acceptor.bind(new InetSocketAddress(port));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public int getPort() {
		return port;
	}

	public void setPort(int port) {
		this.port = port;
	}

	public SocketAcceptor getAcceptor() {
		return acceptor;
	}

	public void setAcceptor(SocketAcceptor acceptor) {
		this.acceptor = acceptor;
	}

	public SocketSessionConfig getSessionConfig() {
		return sessionConfig;
	}

	public void setSessionConfig(SocketSessionConfig sessionConfig) {
		this.sessionConfig = sessionConfig;
	}

}
handler:

package com.lele.test.mina.server.acceptor.handle;

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

import com.lele.test.mina.server.acceptor.pojo.ApplyKeyRequest;
import com.lele.test.mina.server.acceptor.pojo.ApplyKeyResponse;

public class MinaServerHandler extends IoHandlerAdapter {
	
	public void sessionCreated(IoSession session) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("session is created!");
	}

	public void sessionOpened(IoSession session) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("session is Opened!");
	}

	public void sessionClosed(IoSession session) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("session is Closed!");
	}

	public void sessionIdle(IoSession session, IdleStatus status)
			throws Exception {
		// TODO Auto-generated method stub

	}

	public void exceptionCaught(IoSession session, Throwable cause)
			throws Exception {
		// TODO Auto-generated method stub

	}

	public void messageReceived(IoSession session, Object message)
			throws Exception {
		if(message instanceof UserReq){
			
			System.out.println(((UserRequest) message).getUsername());
		}
		//准备返回的数据!
		UserRes a = new UserRes();
		a.setSay("Mr.S say helloWorld!!!");
		//此处与客户端的write一致,会调用filter进行转码,转成Byte[]
		session.write(a);
	}

	public void messageSent(IoSession session, Object message) throws Exception {
		// TODO Auto-generated method stub

	}

}
接收完数据后,会自动关闭session。创建SESSION与打开session都是自动完成的。只要注册了handle~


查看一下SocketAcceptor的代码,继承自IoAcceptor~

几个接口,获取配置、IP端口等信息、是否暂停等。

在IoAcceptor中,有一个接口

IoSession newSession(SocketAddress remoteAddress, SocketAddress localAddress);

将会话绑定到客户端与服务端。怎么绑定的,没找到啊。。。

public void messageReceived(IoSession session, Object message)
			throws Exception {
		if(message instanceof UserReq){
			
			System.out.println(((UserRequest) message).getUsername());
		}
		//准备返回的数据!
		UserRes a = new UserRes();
		a.setSay("Mr.S say helloWorld!!!");
		//此处与客户端的write一致,会调用filter进行转码,转成Byte[]
		session.write(a);
	}
服务启动时加了过滤器,所以这面message读过来就已经解码成UserReq了

补充:

跟踪一下服务器端的线程,

MINA一共三种线程。

 第一类线程:NioSocketAcceptor 唯一。用于bind监听端口,bind一次创建一个。客户端发送请求时,将请求发送给第二类线程处理。
 第二类线程:Nioprocessor 处理客户端请求。每个请求1个线程。满了等待。acceptor = new NioSocketAcceptor(4);创建最大4个线程。handler中的sessionCreated
 第三类线程:处理业务逻辑的线程,使用过滤器添加。第二类线程接收请求后转给第三类请求处理。handler中的从sessionOpen到close。
如果不添加过滤器,那么业务处理将在第二类线程中完成。


		acceptor = new NioSocketAcceptor(4);
		//第三类线程
		//acceptor.getFilterChain().addLast("threadPool", new ExecutorFilter(Executors.newCachedThreadPool()));
		
		


使用可重用的线程池,当现有线程有可用则继续使用,如没有,创建新的线程。满了继续添加新的(PS:适合短连接。用完就销毁。提高性能啊!有机会测试一下。看最多能整多少个线程~)
Executors.newCachedThreadPool()
还有一种,创建固定个数的线程池,也是可重用的,只不过限制个数nThreads,满了会阻塞

newFixedThreadPool(int nThreads)


需要恶补一下线程方面的知识了~



### Dubbo 的底层通信协议实现原理 Dubbo 是一个高性能的 Java 分布式服务框架,其核心功能之一是通过自定义的 RPC 协议实现远程过程调用。以下是关于 Dubbo 底层通信协议的具体实现原理: #### 1. 自定义 Dubbo RPC 协议 Dubbo 使用了一种基于 TCP/IP 的自定义进制协议来完成服务间的通信[^1]。这种协议的设计目标是为了提高传输效率并减少网络开销。具体而言,Dubbo 协议的消息结构通常由以下几个部分组成: - **魔数 (Magic Number)**:用于标识这是一个 Dubbo 协议的数据包。 - **序列化方式**:指定消息体使用的序列化算法(如 Hessian、Kryo 或 Protobuf)。 - **标志位**:表示该消息是否为请求/响应以及是否有异常发生等状态信息。 - **数据长度**:指示后续实际负载数据的字节大小。 - **正文内容**:包含具体的业务参数或返回值。 这些字段共同构成了 Dubbo 数据帧的标准格式,从而使得两端能够高效解析彼此间交换的信息。 #### 2. 基于 Socket 的消息传递机制 在 Dubbo 中,所有的请求应答均依赖底层的 Socket 进行传输[^3]。当消费者发起一次远端方法调用时,它会先构建好对应的 Request 对象并通过网络将其打包成上述提到的那种标准化形式发送出去;此同时,在另一侧提供者监听到来自外部连接之后,则负责解码传入流中的原始比特串还原成为可操作的对象实例供本地逻辑进一步处理完毕后再按照相同流程反向构造 Response 并且回馈回去形成闭环交互模式。 值得注意的是,尽管整个 I/O 操作看似同步执行但实际上由于采用了 Netty/Mina 等 NIO 技术库作为支撑所以本质上还是属于非阻塞型设计——这意味着即使是在等待对方回复期间也不会占用过多计算资源而是交还控制权给事件循环继续处理其他任务直到真正获取到最终结果为止才会重新激活关联上下文恢复原有链条上的下一步动作。 #### 3. 异步回调模型 正如前面所描述那样,一旦某个线程完成了初始阶段的任务即将携带必要元数据封装好的指令提交至输出缓冲区后即可立即释放不再关心后续进展如何因为真正的反馈将会被专门分配出来的工作者池接管下来单独运行直至结束才把成果交付回原来位置处以便应用程序层面可以正常接收利用。这样的架构极大提升了系统的吞吐能力和并发性能尤其适用于大规模集群环境下频繁发生的跨节点通讯场景之中表现尤为突出显著优于传统单一线性顺序作业的方式。 ```java // 示例代码展示了一个简单的 Dubbo 客户端和服务端之间的交互过程 public class SimpleDubboExample { public static void main(String[] args) throws Exception { // 创建 Dubbo 配置对象... ReferenceConfig<GreetingService> reference = new ReferenceConfig<>(); reference.setInterface(GreetingService.class); GreetingService greetingService = reference.get(); String message = greetingService.sayHello("World"); System.out.println(message); // 输出服务器返回的内容 // ...省略更多配置细节 } } ``` 以上就是有关 Dubbo 如何在其内部达成高效的远程调用背后隐藏的技术秘密概述说明版本啦! ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值