2019独角兽企业重金招聘Python工程师标准>>>

不少的朋友在接触到smart-socket后,一上来就想写一个字符串通信的案例。例如客户端发送"Hello Server!",服务端接收到该消息并响应"Hi Client!"。但最终发现客户端可以成功将消息发送出去,但服务端就是无法正常接收。那是不是这个smart-socket框架不行?为什么原先用Netty很简单就实现了?

也许您是第一次接触通信,又或者此前有过一些通信编程经历,但只要无法用smart-socket写出一个简单的字符串通信示例,那说明您的通信之旅还未入门。本文尽量给大家解释清楚通信编程的常见套路,此后大家可以轻松玩转socket。

我们以两个人的对话场景为例,A对B说:"我叫A我今年3岁"。从这句话中,我们很容易解读出A对B传递了两个消息,一个是“我叫A”,另一个是“我今年3岁”。人为识别一句话是一件很自然的事,我们甚至不用去思考为什么我们可以从一句话中解读出多个消息,那是一种本能。在这个本能的背后有一套非常复杂的“算法”在帮你准确的识别并分析日常交流的信息。但是在计算机要模拟现实世界的信息通信场景,就需要由程序员为机器赋予消息识别能力,这个能力也是通信中非常重要的环节:信息编解码。

同样是“我叫A我今年3岁”,人可以通过逐个文字读取,结合上下文的语义分析识别,最终解析出两个消息,而将这套算法转换成机器算法却是一件非常困难的事。不过我们可以采用机器更容易接受的方式来实现这个功能,接下里给大家介绍两种。

方案一

首先,两个通信机器可以事先约定好在每一个消息之前,先告诉对方这个消息长度多少,这样在传输的过程中无论一次性传递多少个消息,对方都能准确识别出。例如机器A与机器B的通信方式可以是这样的。A告知B:“这个消息3个字,我叫A,这个消息5个字,我今年3岁”,网络传输的形态就是“3我叫A5我今年3岁”。机器B收到这串内容之后就很容易解析出A传递的两个消息,只要先识别出即将解析消息的长度,再读取指定长度的数据便是一个完整的消息。

方案二

机器A可以与机器B约定好“接下来我的消息都以某个分割符为标志,且这个分隔符肯定不会出现于消息内容中的”。比如双方约定好的分隔符为逗号,那么双方通信的内容本身必然不能出现该符号。此时机器A传输给B的数据为“我叫A,我今年3岁,”,机器B通过分隔符便识别出了两个消息。

总之大家要谨记两点:

  1. 你的程序没有识别白话文的能力;
  2. 绝大部分的通信编解码都可按照本文提供的两种方案处理。

如果您的悟性还不错的话,文章看到此处便完结了。如果本文解释的还不够清楚,那接下来用代码来给大家示范方案一的实现。

  1. 约定双方通信的编解码协议
/*** @author 三刀* @version V1.0 , 2018/8/25*/
public class StringProtocol implements Protocol<String> {private static final int INT_LENGTH = 4;@Overridepublic String decode(ByteBuffer readBuffer, AioSession<String> session, boolean eof) {//识别消息长度if (readBuffer.remaining() < INT_LENGTH) {return null;}//判断是否存在半包情况int len = readBuffer.getInt(0);if (readBuffer.remaining() < len) {return null;}readBuffer.getInt();//跳过length字段byte[] bytes = new byte[len - INT_LENGTH];readBuffer.get(bytes);return new String(bytes);}@Overridepublic ByteBuffer encode(String msg, AioSession<String> session) {byte[] bytes = msg.getBytes();ByteBuffer buffer = ByteBuffer.allocate(INT_LENGTH + bytes.length);buffer.putInt(INT_LENGTH + bytes.length);buffer.put(bytes);buffer.flip();return buffer;}
}
  1. 服务端实现消息处理逻辑并启动服务
/*** @author 三刀* @version V1.0 , 2018/8/25*/
public class StringServerProcessor implements MessageProcessor<String> {public static void main(String[] args) throws IOException {AioQuickServer<String> server = new AioQuickServer<>(8080, new StringProtocol(), new StringServerProcessor());server.start();}@Overridepublic void process(AioSession<String> session, String msg) {System.out.println("收到客户端消息:" + msg);try {session.write("服务端收到了你的消息:" + msg);} catch (IOException e) {e.printStackTrace();}}@Overridepublic void stateEvent(AioSession<String> session, StateMachineEnum stateMachineEnum, Throwable throwable) {}
}
  1. 客户端发送消息并接受服务的响应
/*** @author 三刀* @version V1.0 , 2018/8/25*/
public class StringClientProcessor implements MessageProcessor<String> {private AioSession<String> session;public static void main(String[] args) throws IOException, InterruptedException, ExecutionException {StringClientProcessor processor = new StringClientProcessor();AioQuickClient<String> client = new AioQuickClient<>("localhost", 8080, new StringProtocol(), processor);client.start();int i = 0;while (i++ < 10) {processor.getSession().write("Hello:" + i);}Thread.sleep(1000);client.shutdown();}@Overridepublic void process(AioSession<String> session, String msg) {System.out.println("收到服务端消息:" + msg);}@Overridepublic void stateEvent(AioSession<String> session, StateMachineEnum stateMachineEnum, Throwable throwable) {if (stateMachineEnum == StateMachineEnum.NEW_SESSION) {this.session = session;}}public AioSession<String> getSession() {return session;}
}

如果您是坚持到文末的读者,希望能Star并支持一下我们的项目smart-socket,多谢!

转载于:https://my.oschina.net/u/2385344/blog/1933949

smart-socket如何实现字符串通信相关推荐

  1. python socket模块实现udp通信_Python基于socket模块实现UDP通信功能示例

    Python基于socket模块实现UDP通信功能示例 本文实例讲述了Python基于socket模块实现UDP通信功能.分享给大家供大家参考,具体如下: 一 代码 1.接收端 import sock ...

  2. java web接收tcp_Java多线程实现TCP网络Socket编程(C/S通信)

    开篇必知必会 在前一篇<基于TCP协议网络socket编程(java实现C/S通信)>,实际存在一个问题,如果服务器端在建立连接后发送多条信息给客户端,客户端是无法全部接收的,原因在于客户 ...

  3. Linux Socket 两个客户端通信,服务端作为中转

    Socket 两个客户端通信,服务端作为中转 Socket两个客户端通信,服务端作为中转,通过sockket的通信原理,简单的做了一个以c语言写的服务端,与自己制作的Android app 与树莓派为 ...

  4. 【socket】socket介绍-socket与http服务通信

    之前几篇文章都是介绍了socket的基础知识,包括socket的TCP/IP协议栈,socket的服务端集中常见的实现模式,还有对于socket在内核中都是如何支持和实现的.这篇文章就讲解socket ...

  5. UE4 Socket多线程非阻塞通信【2】

    昨日不可追, 今日尤可为.勤奋,炽诚,不忘初心 紧接着第一部分,别说话,勿打断我游离的思绪我们走我们走... 二.消息结构&收发队列 先不急着往下走,先捋一捋,不知道自己要干什么地走下去是一件 ...

  6. 使用巨控GRM530模块远程通信连接TIA WINCC(异地组网)SIMATIC NET与S7-200 SMART 集成以太网口OPC 通信

    使用巨控GRM530模块远程通信连接TIA WINCC(异地组网)SIMATIC NET与S7-200 SMART 集成以太网口OPC 通信 硬件: S7-200 SMART SR40 PC 机 ( ...

  7. java socket 全双工客户端_[Java教程]用socket模拟实现全双工通信

    [Java教程]用socket模拟实现全双工通信 0 2017-04-04 00:00:14 //源码下载 http://download.csdn.net/detail/qq_24054661/98 ...

  8. 【Java】GUI界面聊天小程序(基于Socket的客户端服务端通信)

    基于Socket的客户端服务端通信--Java GUI界面小程序 Socket概念及其通信过程: Socket是TCP/IP中的基本概念,它负责将TCP/IP包发送到指定的IP地址.也可以看成是在两个 ...

  9. 基于Socket的游戏服务器通信框架的设计与实现

    博客地址:blog.liujunliang.com.cn 开发工具:VS2017.Unity2017 本文介绍使用Socket/TCP来开发客户端与服务器端通信框架 博主使用过PhotonServer ...

最新文章

  1. 不能使用 '';文件已在使用中。
  2. DCMTK:将hardcopy硬拷贝特征曲线文件转换为softcopy软拷贝格式
  3. node --- [express] cookie/session 机制与 中间件的使用(路由守卫)
  4. PHP连接PGSQL
  5. mysql密码高级_mysql高级操作
  6. The Model Driven Software Network
  7. 又一个“众所周知”的DAL层设计BUG
  8. No Pain No Game
  9. DISK 100% BUSY,谁造成的?
  10. 解决Win11安装Keil芯片包失败/软件卡死/无法解压的问题
  11. java 僵尸进程_僵尸进程ZOMBIE
  12. svn update出现database is locked
  13. Java常用类--日期时间相关的类
  14. 新生宝宝取名大全:带梓字寓意大气的男孩名字
  15. item_search_img - 按图搜索淘宝商品(拍立淘)
  16. 呼吸系统疾病病人的护理题库【1】
  17. APP下载链接点击量如何统计?
  18. A 完全k叉树(CCPC-Wannafly Comet OJ 夏季欢乐赛(2019))
  19. “不务正业”斗地主?AI青年查道琛想做“被人看到”的研究
  20. java pdfbox2 中文乱码_Java用pdfbox或icepdf转换PDF为图片时,中文乱码问题

热门文章

  1. 昌宁一中高考成绩表查询2021,昌宁县一中20182019学年上学期高二数学月考试题含解析.docx...
  2. python 播放 wav 文件
  3. 七、处理机调度概念、层次
  4. javascript 水平文字垂直滚动
  5. 解决Redis报错:MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist
  6. 手机app软件测试教程,手机app制作软件测试app的技巧和方式(上)
  7. 大数据集合求交集_通达信北上资金+盘面分析sp版面,智能大数据集合,筹码占比指标...
  8. Docker Compose安装
  9. 复合的赋值运算符例题_Java千问:关于Java语言复合赋值运算符的两个问题,快来瞧瞧!...
  10. android 组件导出安全,App安全检测实践基础:组件安全(二)