C# protobuf客户端连接JavaNetty+protobuf服务器(一)

来源:杨PPP 发布时间:2018-11-21 15:45:09 阅读量:1105

网络上下载protoc 和 protogen 工具,我的百度云盘地址,主要用到红框内两个。

http://pan.baidu.com/s/1bpwFcmF


(1)创建一个protoc.bat (名字随意起的),添加以下内容。我的protoc.exe和protogen.exe已经添加到环境变量里面了。

echo on

protoc.exe --descriptor_set_out=userLogin.protobin --include_imports userLogin.proto

protogen.exe userLogin.protobin


(2)创建文件 userLogin.proto(名字随意起的),添加以下内容

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脚本,可以看到如下结构。


(3)编译Java+protobuf协议文件

创建脚本 protoJava.bat (名字随意起的),添加以下内容。

echo on

protoc.exe --java_out=./ userLogin.proto

注意userLogin.proto 前边与斜杠有空格。

运行后生成 ProtoTest/UsrLogin.java文件


(4)eclipse新建maven项目,引入 编译后的Java文件

放入合适的包,修改对应的类名,修改成自己本地对应的包名。


maven项目中引入合适的2.5.0版本的protobuf-Java依赖


(5)vs2012新建C#项目,控制台应用程序

(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)

        {

            //设定服务器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)); //配置服务器IP与端口  

                Console.WriteLine("连接服务器成功");

            }

            catch (Exception ex)

            {

                Console.WriteLine("连接服务器失败,请按回车键退出!" + ex);

                return;

            }

 

            //通过clientSocket接收数据 [暂不使用]

            //int receiveLength = clientSocket.Receive(result);

            //Console.WriteLine("接收服务器消息:{0}", receiveLength);

 

            //通过 clientSocket 发送数据  

            for (int i = 0; i < 5; i++)

            {

                try

                {

                    //构建数据

 

                    //封装protobuf empBean实例化

                    ProtoTest.TestInfo.Builder empBeanBuilder = ProtoTest.TestInfo.CreateBuilder();

 

                    empBeanBuilder.SetTest("QQ号码");

                    empBeanBuilder.SetNum(1422020);

 

                    //建立Bean

                    ProtoTest.TestInfo SendEmpBean = empBeanBuilder.Build();

 

                    //发送数据

 

                    //转为byte字节

                    byte[] buf = SendEmpBean.ToByteArray();

                    //通过socket发送

                    clientSocket.Send(buf);

                    //休眠500毫秒

                    Thread.Sleep(500);

 

 

                    Console.WriteLine("向服务器发送消息");

                }

                catch (Exception ex)

                {

                    break;

                }

            }

            Console.WriteLine("发送完毕,按回车键退出");

            Console.ReadLine();

 

        }

    }

}

(9)添加Java服务端,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("服务已启动...");

server.start(7397);

}

 

public void start(int port) throws Exception {

// 配置服务端的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) // 最大客户端连接数为128

.childOption(ChannelOption.SO_KEEPALIVE, true);

// 绑定端口,同步等待成功

ChannelFuture f = b.bind(port).sync();

// 等待服务端监听端口关闭

f.channel().closeFuture().sync();

} finally {

// 优雅退出,释放线程池资源

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)测试运行,可以看到客户端窗口发送了5条信息,服务端收到5条信息。大功告成。




标签: 服务器搭建
分享:
评论:
你还没有登录,请先