來源:楊PPP 發(fā)布時間:2018-11-21 15:45:09 閱讀量:1107
網(wǎng)絡(luò)上下載protoc 和 protogen 工具,我的百度云盤地址,主要用到紅框內(nèi)兩個。
http://pan.baidu.com/s/1bpwFcmF
(1)創(chuàng)建一個protoc.bat (名字隨意起的),添加以下內(nèi)容。我的protoc.exe和protogen.exe已經(jīng)添加到環(huán)境變量里面了。
echo on
protoc.exe --descriptor_set_out=userLogin.protobin --include_imports userLogin.proto
protogen.exe userLogin.protobin
(2)創(chuàng)建文件 userLogin.proto(名字隨意起的),添加以下內(nèi)容
package ProtoTest;
message TestInfo{
required string test = 1;
optional int32 num = 2;
}
message Msg{
required int32 id = 1;
optional TestInfo msg = 2;
optional string str = 3 [default="Test String"];
}
運行bat腳本,可以看到如下結(jié)構(gòu)。
(3)編譯Java+protobuf協(xié)議文件
創(chuàng)建腳本 protoJava.bat (名字隨意起的),添加以下內(nèi)容。
echo on
protoc.exe --java_out=./ userLogin.proto
注意userLogin.proto 前邊與斜杠有空格。
運行后生成 ProtoTest/UsrLogin.java文件
(4)eclipse新建maven項目,引入 編譯后的Java文件
放入合適的包,修改對應(yīng)的類名,修改成自己本地對應(yīng)的包名。
maven項目中引入合適的2.5.0版本的protobuf-Java依賴
(5)vs2012新建C#項目,控制臺應(yīng)用程序
(6)添加userLogin.cs文件,引入Google.ProtocolBuffers.dll,從云盤中protoc文件夾中可以找到到。
(7)修改UserLogin錯誤為,這個可能是個bug,我還不知道原因,但是仿照別的文件做了正確修改。
(8)修改C#的program.cs文件,作為socket客戶端。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using Google.ProtocolBuffers;
//參考http://www.itstack.org/?post=17
namespace ProtoBufTest01
{
class Program
{
static void Main(string[] args)
{
//設(shè)定服務(wù)器IP地址
IPAddress ip = IPAddress.Parse("127.0.0.1");
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
clientSocket.Connect(new IPEndPoint(ip, 7397)); //配置服務(wù)器IP與端口
Console.WriteLine("連接服務(wù)器成功");
}
catch (Exception ex)
{
Console.WriteLine("連接服務(wù)器失敗,請按回車鍵退出!" + ex);
return;
}
//通過clientSocket接收數(shù)據(jù) [暫不使用]
//int receiveLength = clientSocket.Receive(result);
//Console.WriteLine("接收服務(wù)器消息:{0}", receiveLength);
//通過 clientSocket 發(fā)送數(shù)據(jù)
for (int i = 0; i < 5; i++)
{
try
{
//構(gòu)建數(shù)據(jù)
//封裝protobuf empBean實例化
ProtoTest.TestInfo.Builder empBeanBuilder = ProtoTest.TestInfo.CreateBuilder();
empBeanBuilder.SetTest("QQ號碼");
empBeanBuilder.SetNum(1422020);
//建立Bean
ProtoTest.TestInfo SendEmpBean = empBeanBuilder.Build();
//發(fā)送數(shù)據(jù)
//轉(zhuǎn)為byte字節(jié)
byte[] buf = SendEmpBean.ToByteArray();
//通過socket發(fā)送
clientSocket.Send(buf);
//休眠500毫秒
Thread.Sleep(500);
Console.WriteLine("向服務(wù)器發(fā)送消息");
}
catch (Exception ex)
{
break;
}
}
Console.WriteLine("發(fā)送完畢,按回車鍵退出");
Console.ReadLine();
}
}
}
(9)添加Java服務(wù)端,netty框架
maven項目 pom.xml中添加依賴
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.14.Final</version>
</dependency>
如圖:共新增三個Java文件。
package protobuf.userLogin;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
public class HttpServer {
private static Log log = LogFactory.getLog(HttpServer.class);
public static void main(String[] args) throws Exception {
HttpServer server = new HttpServer();
log.info("服務(wù)已啟動...");
server.start(7397);
}
public void start(int port) throws Exception {
// 配置服務(wù)端的NIO線程組
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new ServerHandler());
}
}).option(ChannelOption.SO_BACKLOG, 128) // 最大客戶端連接數(shù)為128
.childOption(ChannelOption.SO_KEEPALIVE, true);
// 綁定端口,同步等待成功
ChannelFuture f = b.bind(port).sync();
// 等待服務(wù)端監(jiān)聽端口關(guān)閉
f.channel().closeFuture().sync();
} finally {
// 優(yōu)雅退出,釋放線程池資源
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
}
package protobuf.userLogin;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
public class ServerHandler extends ChannelInboundHandlerAdapter {
private static Log log = LogFactory.getLog(ServerHandler.class);
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
super.handlerAdded(ctx);
System.out.println(ctx.channel().id() + "進來了");
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
super.handlerRemoved(ctx);
System.out.println(ctx.channel().id() + "離開了");
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("ServerHandler ========================= ");
ByteBuf buf = (ByteBuf) msg;
byte[] req = new byte[buf.readableBytes()];
buf.readBytes(req);
UserLoginDoData.doData(req);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
// TODO Auto-generated method stub
ctx.close();
}
}
package protobuf.userLogin;
public class UserLoginDoData {
public static void doData(byte[] result) throws Exception{
UserLogin.TestInfo msg = UserLogin.TestInfo.parseFrom(result);
System.out.println("number == " + msg.getNum() + " test == " + msg.getTest());
}
}
(10)測試運行,可以看到客戶端窗口發(fā)送了5條信息,服務(wù)端收到5條信息。大功告成。