前言:
计划从这篇文章开始,【Hello World系列】分类下的文章都采取【三问+文档+Demo】的形式介绍新技术。
为什么要用这样的思路呢?因为,我觉得,很多时候,技术其实就是一个工具。可以想象个这样的场景:
别人把一个斧头样的物品递到你手上,接着什么话都不说,那么一脸蒙蔽的你肯定心里是有很多问题想问的。
首先,你可能会问【这是什么?】,先确定物品名,即【是什么】,对方可能回答【斧头】
接着,你会问【拿来干嘛的?】,了解用途,即【有什么用】,可能回答【砍东西】
再接着,你会问【什么时候会用到?】,知道什么时候可以拿出来使用,即【使用场景】,可能回答【可以拿来砍树】
*以下两点是建立在 假设你对砍树相关的专业知识不太了解 的基础上
然后,你可能会说【砍树的话,应该还有别的工具可以做到吧?】,即【可替代品】,可能回答【锯子也可以做到】
再然后,你就会想知道【那为什么选择用斧头砍树而不用锯子呢?】,即【优缺点】,可能回答【斧头的制作更简单,但是用锯子更省力】
初步了解后,就需要找一个遇到问题时可以参考的【说明书】,即【文档】
另外,如果有人可以亲自示范一下用法作为参考的【例子】就更好了,即【Demo】
这是一个比较适合我的思维方式,也很适合作为这个Hello World系列文章的大纲,希望能够坚持下去。
好了,以下是正文。
【三问之一:是什么】
一个可以实现web socket通讯的java框架
【三问之二:有什么用】
目前我只用来实现基础的web socket通讯
【三问之三:使用场景】
需要客户端和服务器端之间互相发送即时消息的时候,比如即时网络对战的游戏
【三问之四:可替代品】
目前没有发现可以实现web socket通讯的、比这个更好的java框架
【三问之五:优缺点】
优点:上手快,使用简单;缺点:待发现。
【文档】
https://smartboot.gitee.io/book/
【Demo】
项目结构
StringProtocol.java
package org.mandy.demo.hello_smart_socket; import java.nio.ByteBuffer; import org.smartboot.socket.Protocol; import org.smartboot.socket.transport.AioSession; public class StringProtocol implements Protocol<String> { @Override public String decode(ByteBuffer readBuffer, AioSession<String> session) { // |消息头 | 消息体 | // | 6 | S | O | C | K | E | T | // 标志当前readBuffer的position位置 readBuffer.mark(); // 获取消息头内容,此时position会+1 byte length = readBuffer.get(); // 如果消息头记录的长度不等于消息体长度,则返回null,position不动 if (length != readBuffer.remaining()) { return null; } // 按照消息体长度创建byte数组 byte[] b = new byte[length]; // 读取消息体内容放入byte数组 readBuffer.get(b); // 更新标志位 readBuffer.mark(); // 返回字符串 return new String(b); } }
Server.java
package org.mandy.demo.hello_smart_socket; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import org.smartboot.socket.MessageProcessor; import org.smartboot.socket.StateMachineEnum; import org.smartboot.socket.transport.AioQuickServer; import org.smartboot.socket.transport.AioSession; public class Server { static SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public static void main(String[] args) throws IOException { // 构造服务端对象 AioQuickServer<String> server = new AioQuickServer<String>(8999, new StringProtocol(), new MessageProcessor<String>() { // 对解析出来的消息进行处理 public void process(AioSession<String> session, String msg) { System.out.println("收到Client发来的消息[" + df.format(new Date()) + "]:" + msg); // 准备发给Client的内容 String rs = "Hi Client!"; // 内容转成消息体的byte数组 byte[] rb = rs.getBytes(); // 创建消息头的byte数组 byte[] head = {(byte) rb.length}; System.out.println("向Client发送消息[" + df.format(new Date()) + "]:" + new String(rb)); try { // 传送消息头 session.writeBuffer().write(head); // 传送消息体 session.writeBuffer().write(rb); } catch (IOException e) { e.printStackTrace(); } } // 当枚举事件发生时由框架触发该方法 public void stateEvent(AioSession<String> session, StateMachineEnum stateMachineEnum, Throwable throwable) { //System.out.println(stateMachineEnum); } }); // 启动服务端 server.start(); } }
Client.java
package org.mandy.demo.hello_smart_socket; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.ExecutionException; import org.smartboot.socket.MessageProcessor; import org.smartboot.socket.StateMachineEnum; import org.smartboot.socket.transport.AioQuickClient; import org.smartboot.socket.transport.AioSession; public class Client { static SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public static void main(String[] args) throws InterruptedException, ExecutionException, IOException { // 构造客户端对象 AioQuickClient<String> client = new AioQuickClient<String>("127.0.0.1", 8999, new StringProtocol(), new MessageProcessor<String>() { public void process(AioSession<String> session, String msg) { System.out.println("收到Server发来的消息[" + df.format(new Date()) + "]:" + msg); } public void stateEvent(AioSession<String> session, StateMachineEnum stateMachineEnum, Throwable throwable) { //System.out.println(stateMachineEnum); } }); // 启动客户端 AioSession<String> session = client.start(); // 准备发给Client的内容 String ss = "Hello Server!"; byte[] sb = ss.getBytes(); byte[] head = {(byte) sb .length}; System.out.println("向Server发送消息[" + df.format(new Date()) + "]:" + new String(sb)); try { session.writeBuffer().write(head); session.writeBuffer().write(sb); // 冲刷出流 session.writeBuffer().flush(); } catch (IOException e) { e.printStackTrace(); } } }
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.mandy.demo</groupId> <artifactId>hello-smart-socket</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>hello-smart-socket</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.25</version> </dependency> <dependency> <groupId>org.smartboot.socket</groupId> <artifactId>aio-core</artifactId> <version>1.4.2</version> </dependency> </dependencies> </project>
运行效果