HKC T7000钻石版笔记本显示器亮度调节怎么调节模式?

  最近在研究protobuf在项目中的使用,由于我们项目服务端采用的是C++,客户端是cocos2dx-cpp,客户端与服务端的消息传输是直接对象的二进制流。如果客户端一直用C++来写,问题到不大,但是后期有想法将客户端用lua来写(可以实现苹果平台的新增更新),这个时候问题就出现了(传输的消息定义无法在lua中得到扩展)。这个时候就想到了protobuf。
  protobuf原本是google的一个开源项目(网上有很多资料),它的功能是将类似的对象(class)转化成字符串,而且这个字符串比json数据少很多,解析也快了很多。为什么说类似,因为它所需的.proto文件的定义与C++中的class有点区别。
  下面我将介绍项目中使用protobuf。
  1、下载所需资源
    a) protobuf2.4.1 版本的下载(将定义的.proto文件转成 xx_pb.cc和 xx_pb_h)
    b) protoc-gen-lua的下载(将定义的.proto文件转成 xx_pb.lua)
  2、protobuf的使用(windows)
    a)解压下载的protobuf2.4.1文件到C:\protobuf-2.4.1(这个位置可以随便),进入在该目录下的vsprojects文件夹,用vs打开protobuf.sln,进行编译(最好一个一个编译),如果报错,可参考。
编译得到的protoc.exe,libprotobuf.lib,libprotobuf-lite.lib,libprotoc.lib会在项目中用到。
    b)将.proto转成xx_pb.h和xx_pb.cc的方法是:将上步骤得到的 protoc.exe拷贝到.proto文件所在的文件夹,创建一个bat文件,里面写入protoc.exe --proto_path=./ --cpp_out=./ ./person.proto&&& pause(注:person.proto&&是该文件夹下需要转化proto文件)。执行bat文件后,就得到了xx_pb.h和xx_pb.cc文件。
    c)在项目中使用xx_pb.h和xx_pb.cc文件。创建一个c++的控制台程序,项目属性中设置
红线框是下载的protobuf的解压路径。
   将xx_pb.h和xx_pb.cc文件加入项目工程。创建一个Server.h文件。贴入代码(该项目中我引用了boost库)
1 #pragma once
2 #include &boost/asio.hpp&
3 #include &boost/bind.hpp&
4 #include &boost/shared_ptr.hpp&
5 #include "people.pb.h"
6 #pragma comment(lib, "libprotobuf.lib")
7 #pragma comment(lib, "libprotoc.lib")
8 #include &string&
9 #include &iostream&
10 #include "person.pb.h"
13 using namespace
14 class Server
16 private:
boost::asio::io_service& m_
boost::asio::ip::tcp::acceptor m_
typedef boost::shared_ptr&boost::asio::ip::tcp::socket& sock_
21 public:
Server(boost::asio::io_service& nios)
:m_ios(nios),
m_apt(m_ios,boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(),6688)),
void Start()
sock_prt sock(new boost::asio::ip::tcp::socket(m_ios));
m_apt.async_accept(*sock,
boost::bind(&Server::accept_callback,this,boost::asio::placeholders::error,sock)
void accept_callback(const boost::system::error_code& e,sock_prt sock)
cout&&"connect error"&&
cout&&"client:"&&sock-&remote_endpoint().address()&&
per.set_email("");
per.set_id(ncount++);
per.set_name("calvin");
p.set_email("");
p.set_id(ncount++);
p.set_name("calvin");*/
string strD
per.SerializePartialToString(&strData);
char data[100];
strcpy(data,strData.c_str());
sock-&async_write_some(boost::asio::buffer(data),
boost::bind(&Server::write_callback,this,boost::asio::placeholders::error)
void write_callback(const boost::system::error_code& e)
cout&&"write error"&&
&&& 在main函数中调用  
cout&&"server start"&&
boost::asio::io_
Server srv(mios);
mios.run();
catch (exception& e)
cout&&e.what()&&
&& 好了,到目前为止,服务端就搭建好了。
  3、protoc-gen-lua的使用(windows)
&&&&&   a)将下载好的文件解压C:\protoc-gen-lua,里面有三个文件夹:example,plugin,protobuf。在plugin文件夹下创建protoc-gen-lua.bat文件,写入 @python "%~dp0protoc-gen-lua",将最开始编译好的protoc.exe文件拷贝到C:\protoc-gen-lua目录下,创建build_for_lua.bat文件,写入(proto_demo是用来存放 proto文件的,方便转化成xx_pb.lua文件)
rem 切换到.proto协议所在的目录
cd C:\protoc-gen-lua\proto_demo
rem 将当前文件夹中的所有协议文件转换为lua文件
for %%i in (*.proto) do (
"..\protoc.exe" --plugin=protoc-gen-lua="..\plugin\protoc-gen-lua.bat" --lua_out=. %%i
&   b)执行build_for_lua.bat文件将会得到xx_pb.lua文件,将该lua文件加入到cocos2dx的Resources文件加下,另外将C:\protoc-gen-lua\protobuf目录下的所有lua文件(共9个)全部加入到Resources文件夹下,将C:\protoc-gen-lua\protobuf目录下的pb.c文件加入到class文件夹下。修改pb.c文件的 #include &endian.h&为#ifndef _WIN32& #include &endian.h&& #endif。 函数struct_unpack中修改switch(format)之前的代码为
uint8_t format = luaL_checkinteger(L, 1);
const uint8_t* buffer = (uint8_t*)luaL_checklstring(L, 2, &len);
size_t pos = luaL_checkinteger(L, 3);
uint8_t out[8];
&&&&&& c)新建一个pocoClient.h文件,代码如下 (使用了poco库)
1 #include "Poco/Net/StreamSocket.h"
2 #include "Poco/Net/SocketAddress.h"
3 #define BUFFER_SIZE 1024
4 #include &iostream&
5 using Poco::Net::SocketA
6 using Poco::Net::StreamS
7 #include "CCLuaEngine.h"
8 #include "cocos2d.h"
9 extern "C"{
10 #include "lua.h"
11 #include "lualib.h"
12 #include "lauxlib.h"
14 class PocoClient
16 public:
void GetData()
SocketAddress address("127.0.0.1", 6688);
StreamSocket socket(address);
char buffer[BUFFER_SIZE];
while (true)
if (socket.available())
int len = socket.receiveBytes(buffer, BUFFER_SIZE);
buffer[len] = '\0';
std::cout && "" && buffer && std::
LuaFunction(buffer);
33 protected:
34 private:
void LuaFunction(const char* str)
lua_State*
plua=cocos2d::CCLuaEngine::defaultEngine()-&getLuaStack()-&getLuaState();
int result = -1;
lua_getglobal(plua, "getdata");
if(!lua_isfunction(plua,1))
lua_pushstring(plua, str);
int n= lua_pcall(plua, 1, 1,0);
result = (int)lua_tonumber(plua, -1);
lua_pop(plua, 1);
printf("The result is %d\n", result);
   以及代码是从服务端获取数据后,然后调用lua文件里面的getdata方法(注:getdata是全局唯一的,并且该函数所在的文件需要在main.lua里面进行require,不然无法识别到此lua函数)。
&&&&&& getdata函数lua代码如下
1 function getdata(str)
require "person_pb"
local person_pbeee=person_pb.Person()
person_pbeee:ParseFromString(str);
print(person_pbeee.id..person_pbeee.name..person_pbeee.email)
&&&&&& 在AppDelegate.cpp文件开始部分加入
1 extern "C"{
2 #include &lua.h&
3 #include &lualib.h&
4 #include &lauxlib.h&
int luaopen_pb(lua_State *L);
&&& applicationDidFinishLaunching()函数中加入luaopen_pb(tolua_s);并在 &pEngine-&executeScriptFile(path.c_str());代码后加入PocoCp.GetData();就可以调用方法,实现客户端和服务端的通信了。
&&& 4、开发注意事项
&&& a)在调用lua函数的时候,要得到相同的lua环境(与最开始hello.lua(创建cocos2dx-lua 自带的)环境一直),也许要在hello.lua中去引用 该函数所在的文件以及 xx_pb.lua文件
阅读(...) 评论()Unity技术博客 - 基于ProtoBuf协议实现网络传输(下) - 简书
Unity技术博客 - 基于ProtoBuf协议实现网络传输(下)
Unity版本: 5.3
使用语言:
ProtoBuf是Google公司推出的一种二进制序列化工具,适用于数据的网络传输。基于Socket实现时时通信,关于数据粘包的编码和解码处理是必不可少的。
实现功能:
1.基于ProtoBuf序列化对象
2.使用Socket实现时时通信
3.数据包的编码和解码
3.数据包的编码和解码
首先,举个例子,这个月信用卡被媳妇刷爆了,面对房贷车贷的压力,我只能选择分期付款。。。
那么OK了,现在我想问一下,当服务器向客户端发送的数据过大时怎么办呢?
当服务器需要向客户端发送一条很长的数据,也会“分期付款!”,服务器会把一条很长的数据分成若干条小数据,多次发送给客户端。
可是,这样就又有另外一个问题,客户端接受到多条数据之后如何解析?
这里其实就是客户端的解码。server发数据一般采用“长度+内容”的格式,Client接收到数据之后,先提取出长度来,然后根据长度判断内容是否发送完毕。
再次重申,用户在发送序列化好的消息的前,需要先编码后再发送消息;用户在接受消息后,需要解码之后再解析数据(反序列化)。
using UnityE
using System.Collections.G
using System.IO;
/// &summary&
/// 编码和解码
/// &/summary&
public class NetEncode {
/// &summary&
/// 将数据编码 长度+内容
/// &/summary&
/// &param name="data"&内容&/param&
public static byte[] Encode(byte[] data)
//整形占四个字节,所以声明一个+4的数组
byte[] result = new byte[data.Length + 4];
//使用流将编码写二进制
MemoryStream ms = new MemoryStream();
BinaryWriter br = new BinaryWriter(ms);
br.Write(data.Length);
br.Write(data);
//将流中的内容复制到数组中
System.Buffer.BlockCopy(ms.ToArray(), 0, result, 0, (int)ms.Length);
br.Close();
ms.Close();
/// &summary&
/// 将数据解码
/// &/summary&
/// &param name="cache"&消息队列&/param&
public static byte[] Decode(ref List&byte& cache)
//首先要获取长度,整形4个字节,如果字节数不足4个字节
if(cache.Count & 4)
//读取数据
MemoryStream ms = new MemoryStream(cache.ToArray());
BinaryReader br = new BinaryReader(ms);
int len = br.ReadInt32();
//根据长度,判断内容是否传递完毕
if(len & ms.Length - ms.Position)
//获取数据
byte[] result = br.ReadBytes(len);
//清空消息池
cache.Clear();
//讲剩余没处理的消息存入消息池
cache.AddRange(br.ReadBytes((int)ms.Length - (int)ms.Position));
用户接受数据代码如下:
using System.Collections.G
using System.Net.S
/// &summary&
/// 表示一个客户端
/// &/summary&
public class NetUserToken {
//连接客户端的Socket
//用于存放接收数据
public byte[]
//每次接受和发送数据的大小
private const int size = 1024;
//接收数据池
private List&byte& receiveC
private bool isR
//发送数据池
private Queue&byte[]& sendC
private bool isS
//接收到消息之后的回调
public Action&NetModel& receiveCallB
public NetUserToken()
buffer = new byte[size];
receiveCache = new List&byte&();
sendCache = new Queue&byte[]&();
/// &summary&
/// 服务器接受客户端发送的消息
/// &/summary&
/// &param name="data"&Data.&/param&
public void Receive(byte[] data)
UnityEngine.Debug.Log("接收到数据");
//将接收到的数据放入数据池中
receiveCache.AddRange(data);
//如果没在读数据
if(!isReceiving)
isReceiving =
ReadData();
/// &summary&
/// 读取数据
/// &/summary&
private void ReadData()
byte[] data = NetEncode.Decode(ref receiveCache);
//说明数据保存成功
if(data != null)
NetModel item = NetSerilizer.DeSerialize(data);
UnityEngine.Debug.Log(item.Message);
if(receiveCallBack != null)
receiveCallBack(item);
//尾递归,继续读取数据
ReadData();
isReceiving =
/// &summary&
/// 服务器发送消息给客户端
/// &/summary&
public void Send()
if (sendCache.Count == 0) {
isSending =
byte[] data = sendCache.Dequeue ();
int count = data.Length /
for (int i = 0; i & count + 1; i++) {
if (i == count) {
len = data.Length - i *
socket.Send (data, i * size, len, SocketFlags.None);
UnityEngine.Debug.Log("发送成功!");
} catch (Exception ex) {
UnityEngine.Debug.Log(ex.ToString());
public void WriteSendDate(byte[] data){
sendCache.Enqueue(data);
if(!isSending)
isSending =
#成功的道路没有捷径,代码这条路更是如此,唯有敲才是王道。cocoscreator:websocket集成使用protobuf
cocoscreator:websocket集成使用protobuf
cocos creator
var Message = Builder.build(&game.service.data.MsgLoginData&);
var loginMessage = new Message();
loginMessage.set(&UserAccount&,&webTest&);
loginMessage.set(&UserPassWord&,&123456&);
var msgBuf = loginMessage.&span style=&color:#ff0000;&&encode().toBuffer()&/span&;
1.数据打包
在protobuf数据结构填写完成后,即可调用encode().toBuffer()将对象转换为ArrayBuffer对象,使用websockt发送数据即可
var Message = Builder.build(&game.service.data.MsgLoginResult&);
var msg = Message.decode(messageBuff);
if(cc.sys.isNative){
webSocket.onDataReceived(event.data);
var fileReader = new FileReader();
fileReader.onload
= function(progressEvent) {
var arrayBuffer = this. // arrayBuffer即为blob对应的arrayBuffer
webSocket.onDataReceived(arrayBuffer);
fileReader.readAsArrayBuffer(event.data);
} 2.数据接收,数据接收有一个需要注意,需要判断是原生环境还是浏览器环境,如果是浏览器环境websocket收到的data将是BLOB类型,需要将BLOB类型转换为ArrayBuffer,
如果是原生环境,直接使用即可
我的热门文章
即使是一小步也想与你分享今天准备给大家介绍一个c#服务器框架()和一个c#客户端框架()。这两个框架的作者是园区里面的。 首先感谢他的无私开源贡献。之所以要写这个文章是因为群里经常有人问这个客户端框架要如何使用。原因在于服务端框架的文档比较多,客户端的文档比较少,所以很多c#基础比较差的人就不懂怎么玩起来。今天就这里写一个例子希望能给部分人抛砖引玉吧。
参考资料:
SuperSocket文档
我以前在开源中国的一部分文章:
这篇文章选择
来实现,选择是因为服务器有可能用的是java的netty,客户端想用SuperSocket.ClientEngine,而netty我看很多人经常用protobuf。
一、SuperSocket服务器
新建一个项目 ProtobufServer 然后添加 SuperSocket 和 protobuf 的依赖包。
添加protobuf依赖包 输入的搜索词是 Google.ProtocolBuffers
添加SuperSocket依赖包 输入搜索词是 SuperSocket,要添加两个SuperSocket.Engine 和 SuperSocket
上面的工作完成后,我们就应该来实现我们的传输协议了。传输协议打算参考netty的
* 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本身的序列号协议可以参考:
我们先看一下SuperSocket的看看有没有合适我们可以直接拿来用的。因为Length使用的是Base 128 Varints一种处理整数的变长二进制编码算法,所以呢内置的协议实现模板并不能直接拿来使用,所以我们只能自己来实现接口IRequestInfo和IReceiveFilter了,参考:。
这里说明一下:为什么protobuf明明序列化成Protobuf Data 了为什么还要再加一个Length来打包,因为tcp这个流发送会参数粘包、分包,如果不加个协议来解析会读取错误的数据而导致无法反序列化 Protobuf Data (自行谷歌 tcp 粘包、分包)
在实现ProtobufRequestInfo之前要先来考虑一个问题,那就是我们的传输协议是长度+protobuf数据,那么我们根本就无法知道获取到的protobuf数据该如何反序列化。在官方网站提供了一种解决思路:
就是我们可以弄唯一个数据包,然后这个数据包里面必须包含一个枚举值,然后还包含了其他类型的数据包,每一个枚举值对应一个数据包,然后传送过来后,可以用分支判断来获取值。
那我们先设计一个 DefeatMessage.proto包含内容:
import &BackMessage.proto&;
import &CallMessage.proto&;
message DefeatMessage {
enum Type { CallMessage = 1; BackMessage = 2; }
required Type type = 1;
optional CallMessage callMessage = 2;
optional BackMessage backMessage = 3;
然后再把CallMessage和BackMessage补全
message BackMessage {
optional string content = 1;
message CallMessage {
optional string content = 1;
然后在我们的路径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的编码不一致,要改成一致。
相关文件:
生成完c#代码后,我们就要设计ProtobufRequestInfo了。这个比较简单,只要实现IRequestInfo接口。我们这里在实现接口带的属性外另加一个 DefeatMessage 和 DefeatMessage.Types.Type,其中DefeatMessage是为了存储我们解包完数据后反序列化出来的对象,Type是为了方便区分我们应该取出DefeatMessage里面的哪个值。
using SuperSocket.SocketBase.P
namespace ProtobufServer
public class ProtobufRequestInfo : IRequestInfo
public string Key {
public DefeatMessage.Types.Type Type
public DefeatMessage Body { }
public ProtobufRequestInfo (DefeatMessage.Types.Type type, DefeatMessage body)
Key = type.ToString();
ProtobufReceiveFilter的实现
代码比较长,直接看在github上的代码
实现的注意点参考:。主要是对ss里面给我们缓存的数据流进行协议解析。
readBuffer: 接收缓冲区, 接收到的数据存放在此数组里
offset: 接收到的数据在接收缓冲区的起始位置
length: 本轮接收到的数据的长度
toBeCopied: 表示当你想缓存接收到的数据时,是否需要为接收到的数据重新创建一个备份而不是直接使用接收缓冲区
rest: 这是一个输出参数, 它应该被设置为当解析到一个为正的请求后,接收缓冲区还剩余多少数据未被解析
ProtobufRequestInfo Filter (byte[] readBuffer, int offset, int length, bool toBeCopied, out int rest)
var readOffset = offset - m_OffsetD//我们重新计算缓存区的起始位置,这里要说明的是如果前一次解析还有剩下没有解析到的数据,那么就需要把起始位置移到之前最后要解析的那个位置
CodedInputStream stream = CodedInputStream.CreateInstance (readBuffer, readOffset, length);//这个类是Google.ProtocolBuffers提供的
var varint32 = (int)stream.ReadRawVarint32 ();//这里是计算我们这个数据包是有多长(不包含length本身)
if(varint32 &= 0)
var headLen = (int) stream.Position - readO//计算协议里面length占用几位
rest = length - varint32 - headLen + m_ParsedL//本次解析完后缓存区还剩下多少数据没有解析
if (rest &= 0)//缓存区里面的数据足够本次解析
byte[] body = stream.ReadRawBytes(varint32);
DefeatMessage message = DefeatMessage.ParseFrom(body);
var requestInfo = new ProtobufRequestInfo(message.Type,message);
InternalReset();
return requestI
else//缓存区里面的数据不够本次解析,(名词为分包)
m_ParsedLength +=
m_OffsetDelta = m_ParsedL
var expectedOffset = offset +
var newOffset = m_OrigOffset + m_OffsetD
if (newOffset & expectedOffset)
Buffer.BlockCopy(readBuffer, offset - m_ParsedLength + length, readBuffer, m_OrigOffset, m_ParsedLength);
ProtobufAppSession 的实现
using SuperSocket.SocketB
namespace ProtobufServer
public class ProtobufAppSession : AppSession&ProtobufAppSession,ProtobufRequestInfo&
public ProtobufAppSession ()
ProtobufAppServer 的实现
using SuperSocket.SocketB
using SuperSocket.SocketBase.P
namespace ProtobufServer
public class ProtobufAppServer : AppServer&ProtobufAppSession,ProtobufRequestInfo&
public ProtobufAppServer ()
:base(new DefaultReceiveFilterFactory& ProtobufReceiveFilter, ProtobufRequestInfo &())
服务器的实例启动实现
主要是接收到数据的一个方法实现,当然ss里面还带了命令模式的实现,不过这个不在本文章里面说。这里的实现了接收到不同的数据给打印出来,然后接收到CallMessage数据的话就给客户端回发一条信息
private static void AppServerOnNewRequestReceived(ProtobufAppSession session, ProtobufRequestInfo requestInfo)
switch (requestInfo.Type)
case DefeatMessage.Types.Type.BackMessage:
Console.WriteLine(&BackMessage:{0}&, requestInfo.Body.BackMessage.Content);
case DefeatMessage.Types.Type.CallMessage:
Console.WriteLine(&CallMessage:{0}&, requestInfo.Body.CallMessage.Content);
var backMessage = BackMessage.CreateBuilder()
.SetContent(&Hello I am form C# server by SuperSocket&).Build();
var message = DefeatMessage.CreateBuilder()
.SetType(DefeatMessage.Types.Type.BackMessage)
.SetBackMessage(backMessage).Build();
using (var stream = new MemoryStream())
CodedOutputStream os = CodedOutputStream.CreateInstance(stream);
os.WriteMessageNoTag(message);
os.Flush();
byte[] data = stream.ToArray();
session.Send(new ArraySegment&byte&(data));
服务器的代码就到这里,可以编译运行起来看看有无错误。
二、SuperSocket.ClientEngine客户端
与服务器实现相同,先通过NuGet添加 SuperSocket.ClientEngine 和 protobuf 的依赖包。
有三个实现:
把前面实现服务器时候生成的通讯数据包拷贝过来,然后和实现服务器的ProtobufRequestInfo一样,只不过这里只是实现接口IPackageInfo而已
using SuperSocket.SocketBase.Pusing SuperSocket.ProtoB
namespace ProtobufClient
public class ProtobufPackageInfo : IPackageInfo
public ProtobufPackageInfo(DefeatMessage.Types.Type type, DefeatMessage body)
Key = type.ToString();
public string Key { }
public DefeatMessage Body { }
public DefeatMessage.Types.Type Type { }
ProtobufReceiveFilter的实现
这里的数据解析的实现与服务器的实现有点不同,不过下一个版本可能会统一,如果统一起来的话,那么以后数据解析就可以做成和插件一样,同时可以给服务器和客户端使用。
data:也是数据缓存区
rest:缓存区还剩下多少
这个实现与服务器的不同就在BufferList本身就已经有处理分包,就不需要我们自己再做处理。
public ProtobufPackageInfo Filter(BufferList data, out int rest)
var buffStream = new BufferStream();
buffStream.Initialize(data);
var stream = CodedInputStream.CreateInstance(buffStream);
var varint32 = (int) stream.ReadRawVarint32();
if (varint32 &= 0) return default(ProtobufPackageInfo);
var total = data.T
var packageLen = varint32 + (int) stream.P
if (total &= packageLen)
rest = total - packageL
var body = stream.ReadRawBytes(varint32);
var message = DefeatMessage.ParseFrom(body);
var requestInfo = new ProtobufPackageInfo(message.Type, message);
return requestI
return default(ProtobufPackageInfo);
运行主程序实现
具体实现看:
这个真的没有什么好说了。运行效果如下:
这里的打印信息是相对比较简单,大家可以自己下载源码来加些打印数据,让看起来更好看点。
三、java的Netty实现
既然前面提到了Netty,那就顺便实现一个简单的服务器来通讯看看。
使用的是Netty 4.x 参考资料:
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
这几个命令要自己灵活改变们不要死死的硬搬。
生成的代码:
然后创建一个maven项目,添加Netty 和 protobuf 依赖:
&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消息就回复信息给客户端。
import io.netty.channel.ChannelHandlerC
import io.netty.channel.ChannelInboundHandlerA
import io.netty.util.ReferenceCountU
* Created by caipeiyu on 16/6/4.
public class ProtobufServerHandler extends ChannelInboundHandlerAdapter {
public void channelRead(ChannelHandlerContext ctx, Object msg) { // (2)
DefeatMessageOuterClass.DefeatMessage in = (DefeatMessageOuterClass.DefeatMessage)
if(in.getType() == DefeatMessageOuterClass.DefeatMessage.Type.BackMessage){
System.out.print(&BackMessage:&);
System.out.print(in.getBackMessage());
System.out.flush();
}else if(in.getType() == DefeatMessageOuterClass.DefeatMessage.Type.CallMessage){
System.out.print(&CallMessage:&);
System.out.print(in.getCallMessage());
System.out.flush();
DefeatMessageOuterClass.DefeatMessage out =
DefeatMessageOuterClass.DefeatMessage.newBuilder()
.setType(DefeatMessageOuterClass.DefeatMessage.Type.BackMessage)
.setBackMessage(BackMessageOuterClass.BackMessage
.newBuilder().setContent(&Hello I from server by Java Netty&).build())
ctx.write(out);
ctx.flush();
} finally {
ReferenceCountUtil.release(msg); // (2)
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // (4)
// Close the connection when an exception is raised.
cause.printStackTrace();
ctx.close();
ProtobufServer的实现
主要是添加已经有的编码解码和消息接收的类就可以了。
import io.netty.bootstrap.ServerB
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopG
import io.netty.channel.socket.SocketC
import io.netty.channel.socket.nio.NioServerSocketC
import io.netty.handler.codec.protobuf.ProtobufD
import io.netty.handler.codec.protobuf.ProtobufE
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameD
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldP
* Created by caipeiyu on 16/6/4.
public class ProtobufServer {
public static void main(String[] args) {
EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1)
EventLoopGroup workerGroup = new NioEventLoopGroup();
ServerBootstrap b = new ServerBootstrap(); // (2)
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class) // (3)
.childHandler(new ChannelInitializer&SocketChannel&() { // (4)
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
p.addLast(&frameDecoder&, new ProtobufVarint32FrameDecoder());
//构造函数传递要解码成的类型
p.addLast(&protobufDecoder&, new ProtobufDecoder(DefeatMessageOuterClass.DefeatMessage.getDefaultInstance()));
p.addLast(&frameEncoder&, new ProtobufVarint32LengthFieldPrepender());
p.addLast(&protobufEncoder&, new ProtobufEncoder());
//业务逻辑处理
p.addLast(&handler&, new ProtobufServerHandler());
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true); // (6)
// Bind and start to accept incoming connections.
ChannelFuture f = b.bind(2012).sync(); // (7)
// Wait until the server socket is closed.
// In this example, this does not happen, but you can do that to gracefully
// shut down your server.
f.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
整个代码编写完成后,直接运行并打开我们前面的客户端进通讯发数据。运行结果如下:
当然这三个例子直接简单的说明如何使用框架来解决我们的问题,实际开发过程中肯定不只是我们例子的这么点东西,需要考虑的东西还很多,这里只是写一些可以运行起来的例子作为抛砖引玉。希望能给不懂的同学有点启发作用。谢谢您百忙中抽出时间来观看我的分享。
由于本人水平有限,知识有限,文章难免会有错误,欢迎大家指正。如果有什么问题也欢迎大家回复交流。要是你觉得本文还可以,那么点击一下推荐。
阅读(...) 评论()

我要回帖

更多关于 显示器亮度调节软件 的文章

 

随机推荐