SuperSocket与Netty之实现protobuf协议,包括服务端和客户端
今天准备给大家介绍一个c#服务器框架(SuperSocket)和一个c#客户端框架(SuperSocket.ClientEngine)。这两个框架的作者是园区里面的江大渔。 首先感谢他的无私开源贡献。之所以要写这个文章是因为群里经常有人问这个客户端框架要如何使用。原因在于服务端框架的文档比较多,客户端的文档比较少,所以很多c#基础比较差的人就不懂怎么玩起来。今天就这里写一个例子希望能给部分人抛砖引玉吧。
参考资料:
SuperSocket文档 http://docs.supersocket.net/
我以前在开源中国的一部分文章:http://my.oschina.net/caipeiyu/blog
这篇文章选择 protobuf 来实现,选择protobuf是因为服务器有可能用的是java的netty,客户端想用SuperSocket.ClientEngine,而netty我看很多人经常用protobuf。
一、SuperSocket服务器
新建一个项目 ProtobufServer 然后添加 SuperSocket 和 protobuf 的依赖包。
添加protobuf依赖包 输入的搜索词是 Google.ProtocolBuffers
添加SuperSocket依赖包 输入搜索词是 SuperSocket,要添加两个SuperSocket.Engine 和 SuperSocket
上面的工作完成后,我们就应该来实现我们的传输协议了。传输协议打算参考netty的ProtobufVarint32FrameDecoder.java
* BEFORE DECODE (302 bytes) AFTER DECODE (300 bytes)* +--------+---------------+ +---------------+* | Length | Protobuf Data |----->| Protobuf Data |* | 0xAC02 | (300 bytes) | | (300 bytes) |* +--------+---------------+ +---------------+
Protobuf Data是protobuf的序列化结果。Length(Base 128 Varints)是表示Protobuf Data的长度。protobuf本身的序列号协议可以参考:https://developers.google.com/protocol-buffers/docs/encoding
我们先看一下SuperSocket的内置的常用协议实现模版看看有没有合适我们可以直接拿来用的。因为Length使用的是Base 128 Varints一种处理整数的变长二进制编码算法,所以呢内置的协议实现模板并不能直接拿来使用,所以我们只能自己来实现接口IRequestInfo和IReceiveFilter了,参考:使用 IRequestInfo 和 IReceiveFilter 等等其他对象来实现自定义协议。
这里说明一下:为什么protobuf明明序列化成Protobuf Data 了为什么还要再加一个Length来打包,因为tcp这个流发送会参数粘包、分包,如果不加个协议来解析会读取错误的数据而导致无法反序列化 Protobuf Data (自行谷歌 tcp 粘包、分包)
ProtobufRequestInfo的实现
在实现ProtobufRequestInfo之前要先来考虑一个问题,那就是我们的传输协议是长度+protobuf数据
,那么我们根本就无法知道获取到的protobuf数据该如何反序列化。在官方网站提供了一种解决思路:https://developers.google.com/protocol-buffers/docs/techniques#union
就是我们可以弄唯一个数据包,然后这个数据包里面必须包含一个枚举值,然后还包含了其他类型的数据包,每一个枚举值对应一个数据包,然后传送过来后,可以用分支判断来获取值。
那我们先设计一个 DefeatMessage.proto包含内容:
然后再把CallMessage和BackMessage补全
然后在我们的路径packages\Google.ProtocolBuffers.2.4.1.555\tools里面有两个工具protoc.exe 和 protogen.exe,我们可以执行下面的命令来生成我们的c#代码
protoc --descriptor_set_out=DefeatMessage.protobin --proto_path=pack --include_imports pack\DefeatMessage.proto
protogen DefeatMessage.protobin
注意路径要自己修改
如果有报Expected top-level statement (e.g. "message").这么一个错误,那就是你cmd的编码和proto的编码不一致,要改成一致。
相关文件:https://github.com/kotcmm/SuperSocket.ClientEngine.QuickStart/tree/master/ProtobufServer/Pack
生成完c#代码后,我们就要设计ProtobufRequestInfo了。这个比较简单,只要实现IRequestInfo接口。我们这里在实现接口带的属性外另加一个 DefeatMessage 和 DefeatMessage.Types.Type,其中DefeatMessage是为了存储我们解包完数据后反序列化出来的对象,Type是为了方便区分我们应该取出DefeatMessage里面的哪个值。
ProtobufReceiveFilter的实现
代码比较长,直接看在github上的代码ProtobufReceiveFilter的实现
实现的注意点参考:使用 IRequestInfo 和 IReceiveFilter 等等其他对象来实现自定义协议。主要是对ss里面给我们缓存的数据流进行协议解析。
readBuffer: 接收缓冲区, 接收到的数据存放在此数组里
offset: 接收到的数据在接收缓冲区的起始位置
length: 本轮接收到的数据的长度
toBeCopied: 表示当你想缓存接收到的数据时,是否需要为接收到的数据重新创建一个备份而不是直接使用接收缓冲区
rest: 这是一个输出参数, 它应该被设置为当解析到一个为政的请求后,接收缓冲区还剩余多少数据未被解析
ProtobufAppSession 的实现
ProtobufAppServer 的实现
服务器的实例启动实现
参考:http://docs.supersocket.net/v1-6/zh-CN/A-Telnet-Example
代码:https://github.com/kotcmm/SuperSocket.ClientEngine.QuickStart/blob/master/ProtobufServer/Program.cs
主要是接收到数据的一个方法实现,当然ss里面还带了命令模式的实现,不过这个不在本文章里面说。这里的实现了接收到不同的数据给打印出来,然后接收到CallMessage数据的话就给客户端回发一条信息
服务器的代码就到这里,可以编译运行起来看看有无错误。
二、SuperSocket.ClientEngine客户端
与服务器实现相同,先通过NuGet添加 SuperSocket.ClientEngine 和 protobuf 的依赖包。
有三个实现:
ProtobufPackageInfo的实现
把前面实现服务器时候生成的通讯数据包拷贝过来,然后和实现服务器的ProtobufRequestInfo一样,只不过这里只是实现接口IPackageInfo而已
ProtobufReceiveFilter的实现
代码:https://github.com/kotcmm/SuperSocket.ClientEngine.QuickStart/blob/master/ProtobufClient/ProtobufReceiveFilter.cs
这里的数据解析的实现与服务器的实现有点不同,不过下一个版本可能会统一,如果统一起来的话,那么以后数据解析就可以做成和插件一样,同时可以给服务器和客户端使用。
data:也是数据缓存区
rest:缓存区还剩下多少
这个实现与服务器的不同就在BufferList本身就已经有处理分包,就不需要我们自己再做处理。
运行主程序实现
具体实现看:https://github.com/kotcmm/SuperSocket.ClientEngine.QuickStart/blob/master/ProtobufClient/Program.cs
这个真的没有什么好说了。运行效果如下:
这里的打印信息���相对比较简单,大家可以自己下载源码来加些打印数据,让看起来更好看点。
三、java的Netty实现
既然前面提到了Netty,那就顺便实现一个简单的服务器来通讯看看。
使用的是Netty 4.x 参考资料:http://netty.io/wiki/user-guide-for-4.x.html
Netty的实现在网络上有超级多的例子,这里就简单的介绍一下就可以,首先先生成java的通讯包代码
protoc --proto_path=pack --java_out=./ pack/DefeatMessage.proto
protoc --proto_path=pack --java_out=./ pack/BackMessage.proto
protoc --proto_path=pack --java_out=./ pack/CallMessage.proto
这几个命令要自己灵活改变们不要死死的硬搬。
生成的代码:https://github.com/kotcmm/SuperSocket.ClientEngine.QuickStart/tree/master/java/NettyProtobufServer/src/main/java
然后创建一个maven项目,添加Netty 和 protobuf 依赖:https://github.com/kotcmm/SuperSocket.ClientEngine.QuickStart/blob/master/java/NettyProtobufServer/pom.xml
<dependencies> <dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>2.6.1</version> </dependency> <dependency> <groupId>io.netty</groupId> <artifactId>netty-microbench</artifactId> <version>4.1.0.Final</version> </dependency> </dependencies>
ProtobufServerHandler的实现
因为Netty里面已经有帮我们实现了protobuf的解析,所以我们不需要自己实现。我们只要继承ChannelInboundHandlerAdapter然后通过channelRead就可以拿到解析好的对象,然后转换成我们自己的类型,就可以直接使用。这里同样是实现不同类型的消息打印和CallMessage消息就回复信息给客户端。
ProtobufServer的实现
主要是添加已经有的编码解码和消息接收的类就可以了。
整个代码编写完成后,直接运行并打开我们前面的客户端进通讯发数据。运行结果如下:
当然这三个例子直接简单的说明如何使用框架来解决我们的问题,实际开发过程中肯定不只是我们例子的这么点东西,需要考虑的东西还很多,这里只是写一些可以运行起来的例子作为抛砖引玉。希望能给不懂的同学有点启发作用。谢谢您百忙中抽出时间来观看我的分享。
相关文章:
SuperSocket, 可扩展的 Socket 服务器框架
开源项目SuperSocket的学习笔记
使用LogMaster4Net实现应用程序日志的集中管理
原文地址:http://www.cnblogs.com/caipeiyu/p/5559112.html
.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注
SuperSocket与Netty之实现protobuf协议,包括服务端和客户端相关推荐
- netty服务器返回信息关闭,netty4 服务端同步客户端返回的结果
netty是一个异步通讯框架,在有的时候咱们想使用服务端向客户端发送消息,服务端同步等待客户端返回结果真进行下一步的业务逻辑操做.那要怎么作才能同步获取客户端返回的数据呢?这里我用到了JDK中的闭锁等 ...
- WebSocket使用,包括服务端和客户端(JAVA实现)
原文地址 https://www.cnblogs.com/Javi/p/9303020.html
- Netty实战 IM即时通讯系统(八)服务端和客户端通信协议编解码
Netty实战 IM即时通讯系统(八)服务端和客户端通信协议编解码 零. 目录 IM系统简介 Netty 简介 Netty 环境配置 服务端启动流程 客户端启动流程 实战: 客户端和服务端双向通信 数 ...
- netty tcp服务端主动断开客户端_【Netty】服务端和客户端
欢迎关注公众号:[爱编程] 如果有需要后台回复2019赠送1T的学习资料哦!! 本文是基于Netty4.1.36进行分析 服务端 Netty服务端的启动代码基本都是如下: private void s ...
- iOS开发-使用OC搭建自己的Socket 包括服务端和客服端
iOS开发-使用OC搭建自己的Socket 包括服务端和客服端 前言 开发须知 客服端 服务端 两端测试 前言 iOS开发中需要使用到Socket通信的地方,socket分为UDP和TCP,这次分享的 ...
- TCP协议服务端与客户端
一.TCP/IP协议简介 什么是TCP/IP TCP/IP协议是一种用于因特网的通信协议.TCP指传输控制协议(Transmission Control Protocol),IP指网际协议(Inter ...
- Netty源码阅读(2)之——服务端源码梗概
上文我们把客户端源码梗概大致了解了一下,这样再了解服务端源码就轻松一点,我们将从服务端和客户端的区别着手去解析. 目录 区别 ④ ③ ① ⑤ 区别 ④ 客户端:.option(ChannelOptio ...
- 卡牌手机游戏基于HTTP协议的服务端设计方案
背景: 手机游戏平台服务端设计目前主要有基于Socket的状态连接和HTTP无状态连接两种架构.由于手机用户对于网络流量的敏感和网络状态的变化要比PC环境要复杂,因而对于卡牌类游戏基本采用HTTP连接 ...
- Netty学习笔记(二) 实现服务端和客户端
在Netty学习笔记(一) 实现DISCARD服务中,我们使用Netty和Python实现了简单的丢弃DISCARD服务,这篇,我们使用Netty实现服务端和客户端交互的需求. 前置工作 开发环境 J ...
最新文章
- Flume基础及Flume高质量博客合集
- 令人头疼的字符编码的问题
- 初识 JSP---(Servlet映射 / ServletRequest / get与post区别 / 解决乱码)
- 中文简体字-繁体字转换 WEB 服务(源代码)
- uri=http: //java.sun.c om/jsp/jstl/core 出错
- android 5.0 字体,QC8916 修改系统默认字体(Android 5.0)
- Android adb不是内部或外部命令 问题解决
- 深度学习优化算法入门:二、动量、RMSProp、Adam
- Sharding-jdbc视频:当Sharding-jdbc遇到Spring Boot
- CenterOs升级gcc
- centos7镜像文件
- Unity3D 从 ipa 中提取游戏资源
- idea项目工具窗口
- 计算机开机键盘屏幕无反应,戴尔电脑开机键亮但为什么屏幕没有反应
- JAVA 字符串转数组并且进行遍历
- 形式语言与自动机 第4章 正规文法和正规集的性质
- 语音唤醒 mycroft-precise使用记录
- python报错ValueError: Found input variables with inconsistent numbers of samples: [x,y]
- http隧道、https、SSL层、http代理、在线代理、socks代理区别
- CSUST 2007 我爱吃烧烤 题解(状压dp)