smart-socket是什么
smart-socket文档地址
http://smartsocket.mydoc.io/?t=260338
码云地址:
https://gitee.com/smartboot/smart-socket
smart(百度翻译:聪明的;敏捷的;漂亮的;整齐的),从为项目起名开始,便对其寄予了厚望。专注于通信组件的研究与发展,摒弃一切大而全的解决方案,仅提供小而美的基础服务。无论您是从事IOT、IM、RPC,还是其余通信领域的开发工作,相信smart-socket都是非常酷的选择。如果要用一句话来为smart-socket打call,那就是:遇见smart-socket,你就已经赢在起跑线了。
关于开源
JDK7虽然已经发布很长一段时间了,但开源社区对于其AIO的新特性貌似并不热情。对于通信方面的技术诉求,似乎大家都习惯于Netty、Mina。“Stop Trying to Reinvent the Wheel”不要重复造轮子,几乎每个程序员都被灌输过这个概念,理所当然的沉浸在各自的舒适区,享受着开源社区提供的各项技术支撑。举个跟本文相契合的例子,如果工作中遇到通信相关的需求,广大Java程序员脑海里首先想到的必然是Netty或Mina,即便从未接触过Netty/Mina,但在心里认定只有这两个框架才能解决自己面临的问题。这样的现状可能归咎于现在我们太急躁,工作的压力致使没时间给自己充电,尤其是那种不常用且稍微有点深度的技术点,已经没心力再去细细琢磨了。所幸还有一批好学的程序员在工作之余做着一些看似平凡的事,踏踏实实专研这些技术点并作出一些小小的作品,同时为开源社区注入新鲜血液。目前码云上已知的Java AIO项目有tio、Voovan、baseio以及本文的主角:smart-socket,这几个作品还无任何一款能形成足够的影响力被广大Javaer认可,但通过开源的推广与磨练,相信未来AIO的开源环境会比现在更加繁荣。
smart-socket立项之初便已严苛的要求进行开发,追求各方面都达到极致。首先,smart-socket是个非常轻量级的项目,只有依赖log4j2作为项目的日志组件。smart-socket发布的jar包仅仅20KB,简洁的接口设计可以非常方便的在业务中接入通信服务。不过我们更期望看到的是接触到smart-socket的朋友可以将其作为学习Java Socket编程的素材,如果smart-socket能在这方面给予您一丝帮助,那我便会绝对自己做了一件有意义的事。
官方指南假设您已了解ByteBuffer,并对Socket编程具备一定基础。如果您刚开始接触Socket,将smart-socket作为您的第一步可能不是个好的决定。
Maven依赖
smart-socket已上传至Maven仓库,使用前需要向其引入您的项目工程中。
<!-- https://mvnrepository.com/artifact/org.smartboot.socket/aio-core -->
<dependency>
<groupId>org.smartboot.socket</groupId>
<artifactId>aio-core</artifactId>
<version>1.3.2</version>
</dependency>
通信开发
基于smart-socket进行通信服务的开发,主要有三个步骤:
- 协议编解码
- 消息处理
- 启动服务
接下来我们会通过一个简单例子来演示如何通过smart-socket开发服务端与客户端程序。为简化操作,服务端与客户端交互的数据为一个整型数据。
一、协议编解码
正常情况下服务端与客户端通信共用同一套协议规则,因此我们只需编写一份协议编解码实现即可。如下所示,协议编解码的需要实现接口Protocol。
public class IntegerProtocol implements Protocol<Integer> {
private static final int INT_LENGTH = 4;
@Override
public Integer decode(ByteBuffer data, AioSession<Integer> session, boolean eof) {
if (data.remaining() < INT_LENGTH)
return null;
return data.getInt();
}
@Override
public ByteBuffer encode(Integer s, AioSession<Integer> session) {
ByteBuffer b = ByteBuffer.allocate(INT_LENGTH);
b.putInt(s);
b.flip();
return b;
}
}
上述代码很简单,一个整数的长度为4byte,所以只要长度大于等于4,我们就能解析到一个整数。
二、消息处理
业务消息的处理需要实现接口MessageProcessor
,该接口只有两个方法:process
,stateEvent
。其中 stateEvent用于定义AioSession状态机的监控与处理。process则会处理每一个接收到的业务消息。
服务端
public class IntegerServerProcessor implements MessageProcessor<Integer> {
@Override
public void process(AioSession<Integer> session, Integer msg) {
Integer respMsg = msg + 1;
System.out.println("接受到客户端数据:" + msg + " ,响应数据:" + (respMsg));
try {
session.write(respMsg);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void stateEvent(AioSession<Integer> session, StateMachineEnum stateMachineEnum, Throwable throwable) {
}
}
客户端
public class IntegerClientProcessor implements MessageProcessor<Integer> {
private AioSession<Integer> session;
@Override
public void process(AioSession<Integer> session, Integer msg) {
System.out.println("接受到服务端响应数据:" + msg);
}
@Override
public void stateEvent(AioSession<Integer> session, StateMachineEnum stateMachineEnum, Throwable throwable) {
switch (stateMachineEnum) {
case NEW_SESSION:
this.session = session;
break;
default:
System.out.println("other state:" + stateMachineEnum);
}
}
public AioSession<Integer> getSession() {
return session;
}
}
三、启动服务
服务端
public class IntegerServer {
public static void main(String[] args) {
AioQuickServer server = new AioQuickServer()
.bind(8888)
.setProtocol(new IntegerProtocol())
.setProcessor(new IntegerServerProcessor());
try {
server.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端
public class IntegerClient {
public static void main(String[] args) throws Exception {
IntegerClientProcessor processor=new IntegerClientProcessor();
AioQuickClient aioQuickClient=new AioQuickClient()
.connect("localhost",8888)
.setProtocol(new IntegerProtocol())
.setProcessor(processor);
aioQuickClient.start();
processor.getSession().write(1);
Thread.sleep(1000);
aioQuickClient.shutdown();
}
}