基于networkcomms V3通信框架的c#服务器与java客户端进行通信之Protobuf探讨

在上一篇 基于networkcomms V3通信框架的c#服务器与java客户端进行通信探讨  中探讨了在C#端与Java端通信中传递字符,有朋友提到如果传递int类型的整数,会出现编码的问题。

到网上找到了一篇文章《 使用protobuf进行C#与Java通信 》进行学习 ,使用protobuf进行编码,传递数据,好像这样可以避免编码的问题。

(虽然编码问题解决了,但是粘包问题并没有解决,有经验的朋友介绍下怎样解决粘包的问题)

服务器端基于networkcomms V3 C#通信框架. networkcomms 通信框架是商业版的,本文也并不提供。

引用原文:http://blog.csdn.net/wangpei421/article/details/8004903

用protobuf进行C#与Java通信
        在之前已写一篇关于ProtoBuf的文章了,主要是.net版本的实现。今天主要是讲如何利用ProtoBuf定义一个协议,来实现C#与Java双方进行通信(这个通信指的是双方数据协议,而不是通信协议。)
ProtoBuf 应用场景
       个人认为,主要用于数据交互和共享,此种情况需要双方制定一个特定的数据结构。那么使用ProtoBuf 定义一个数据结构,然后大家从这个描述文件,各自生成自己使用的编程语言对应的代码文件,再使用这些代码对双方的数据进行处理。那么,只要都遵守这个数据文件格式,数据共享就可以实现夸平台。如果数据描述文件做了修改,只要遵守一定的规则,那么原有数据还是可以兼容使用的。这个就是做了一个平台无关的文件与平台和语言相关的数据对象之间的适配转化工作,就和很多xml解析器一样。

实现C#与Java通信步骤
       1.定义协议
       创建一个以.proto为后缀的文件,本篇创建了一个名为msg.proto的消息文件,具体信息如下:
package tutorial;
option java_package = "com.protobuftest.protobuf"; (生成Java类时包名;C#类的命名空间)
option java_outer_classname = "PersonProbuf"; (生成Java、C#类的类名)

message Person {
  required string name = 1;
  required int32 id = 2;
  optional string email = 3;
  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }
  message PhoneNumber {
    required string number = 1;
    optional PhoneType type = 2 [default = HOME];
  }
  repeated PhoneNumber phone = 4;
  message CountryInfo {
          required string name = 1;
          required string code = 2;
          optional int32 number = 3;
  }
}
message AddressBook {
  repeated Person person = 1;
}
  package在Java里面代表这个文件所在的包名,在c#里面代表该文件的命名空间;
 message代表一个类;
 required 代表该字段必填;
 optional 代表该字段可选,并可以为其设置默认值,默认值格式 :[defalut=Home],它是一个枚举类型。

引用原文:

 2.双方都编译.proto文件(本篇文章主要用的是2.4.1版本的protobuf)
    proto可以在Linux、Windows下编译。
     protobuf 下载列表请参照:http://code.google.com/p/protobuf/downloads/list  ,选择其中的win版本下载。解压后会得到一个 protoc.exe 文件,此时就可以开始编译了。
           java 的编译的步骤如下:
(1) 打开命令工具 cmd
  (2)     把protoc.exe文件放在D:/protoc 目录下,先cd 到该目录cd D:/protoc
(3) 输入protoc.exe --java_out=./ msg.proto
          此时会发现 D:/protoc目录中多了一个文件夹com\protobuftest\protobuf,即以该proto的package命名的目录,会产生一个Msg.java的文件,这时这个文件就可以使用到我们的java或者android 工程了。
(4) 下载一个protobuf-java-2.4.1.jar的jar 包引用到你的java和android工程里面,之后可以使用你的protobuf了。

C# 的编译步骤:
.net 版的protobuf来源于proto社区,有两个版本。一个版本叫protobuf-net,官方站点:http://code.google.com/p/protobuf-net/  写法上比较符合c#一贯的写法。
另一个版本叫protobuf-csharp-sport , 官方站点:http://code.google.com/p/protobuf-csharp-port/ 写法上跟java上的使用极其相似,比较遵循Google 的原生态写法,跨平台选择此版本比较好。因为你会发现几乎和java的写法没啥两样,本篇也是使用这个版本。
                http://code.google.com/p/protobuf-csharp-port/下载Win版本,编译步骤如下:
(1) 把proto文件放在你解压出来的目录与protoc.exe 、ProtoGen.exe、ProtoGen.exe.config、Google.ProtocolBuffers.dll放于一起。其他文件可以删除或者备份。
(2) 打开命令行cmd,定位于对应的目录里面。
           输入:protoc --descriptor_set_out=msg.protobin --include_imports msg.proto
          msg.protobin是要生成的prtobobin文件,可以使用这个bin文件生成cs文件
               再输入protogen msg.protobin  使用该bin文件生成cs文件,这样你就可以得到该msg.cs 的CSharp版文件了,同时在VS里面使用要引入Google.ProtocolBuffers.dll。

忙了一下午,把相关的工具都找齐了,proto版本与引用的文中的版本号不是一个版本,可以使用

c# 相关protobuf文件

java 相关protobuf文件

服务器端代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using NetworkCommsDotNet;
using NetworkCommsDotNet.DPSBase;
using NetworkCommsDotNet.Tools;

using NetworkCommsDotNet.Connections;
using NetworkCommsDotNet.Connections.TCP;
using System.Net;
using Google.ProtocolBuffers;
using tutorial;

namespace protobufServer
{
    public partial class Form1 : Form
    {
        SendReceiveOptions sro = new SendReceiveOptions(DPSManager.GetDataSerializer<NullSerializer>(), null, null);

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //服务器开始监听客户端的请求
            //开始监听某端口
           //与其他语言通信   禁用ApplicationLayerProtocolStatus
            TCPConnectionListener  listener=new TCPConnectionListener (sro,ApplicationLayerProtocolStatus.Disabled);

            Connection.StartListening(listener, new IPEndPoint(IPAddress.Parse(txtIP.Text), int.Parse(txtPort.Text)));

            button1.Text = "监听中";
            button1.Enabled = false;

            //此方法中包含服务器具体的处理方法。
            StartListening();
        }

        private void StartListening()
        {
            NetworkComms.DisableLogging();

            //array  收到字节
            NetworkComms.AppendGlobalIncomingUnmanagedPacketHandler((header, connection, array) =>
            {
                Person person2 = Person.ParseFrom(array);

                LogInfo.LogMessage(person2.Id + "," + person2.Name + ", " + person2.Email, "日志.txt");
                IList<Person.Types.PhoneNumber> lstPhones = person2.PhoneList;
                foreach (Person.Types.PhoneNumber phoneNumber in lstPhones)
                {

                    LogInfo.LogMessage(phoneNumber.Number.ToString(), "日志.txt");
                }

                //返回一个数据给客户端
                //序列化
                Person.Builder builder = new Person.Builder();
                builder.SetEmail("名山大川@email.com");
                builder.SetId(1);
                builder.SetName("大江东去浪淘尽");
                builder.AddPhone(new Person.Types.PhoneNumber.Builder().SetNumber("12345679").SetType(Person.Types.PhoneType.MOBILE));
                builder.AddPhone(new Person.Types.PhoneNumber.Builder().SetNumber("123456").SetType(Person.Types.PhoneType.HOME));
                Person person = builder.Build();
                byte[] buf = person.ToByteArray();
                connection.SendUnmanagedBytes(buf); 

            });

        }

        private void Form1_FormClosing_1(object sender, FormClosingEventArgs e)
        {
            NetworkComms.Shutdown();
            Environment.Exit(Environment.ExitCode);
        }
    }
}

客户端

服务器端:

java代码

package com.protobuftest.protobuf;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import com.google.protobuf.InvalidProtocolBufferException;
import java.util.List;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.Runtime;
import java.io.IOException;

public class First extends Thread{

    public static byte[] readStream(InputStream inStream) throws Exception {
        int count = 0;
        while (count == 0) {
            count = inStream.available();
        }
        byte[] b = new byte[count];
        inStream.read(b);
        return b;
    }  

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {
        Socket socket = null;

        int j = 0;
        try {

            socket = new Socket("127.0.0.1", 3000);
            if (socket.isConnected()) {
                System.out.println("已建立连接!---");

                   PersonProbuf.Person.Builder builder = PersonProbuf.Person.newBuilder();
                   builder.setEmail("kkk@email.com");
                   builder.setId(1);
                   builder.setName("TestName");
                   builder.addPhone(PersonProbuf.Person.PhoneNumber.newBuilder().setNumber("131111111").setType(PersonProbuf.Person.PhoneType.MOBILE));
                   builder.addPhone(PersonProbuf.Person.PhoneNumber.newBuilder().setNumber("011111").setType(PersonProbuf.Person.PhoneType.HOME));
                   PersonProbuf.Person person = builder.build();
                   byte[] buf = person.toByteArray();

                //2.得到socket读写流
                OutputStream os=socket.getOutputStream();  

                //3.利用流按照一定的操作,对socket进行读写操作  

                os.write(buf);
                os.flush();

                System.out.println("----------------------------------");  

                InputStream ips = socket.getInputStream();
                byte[] rebyte = readStream(ips);  

              //  String resultStr = new String(rebyte, 0, rebyte.length, "UTF-8");
              // System.out.println("收到主机消息:" + resultStr);  

                PersonProbuf.Person person2 = PersonProbuf.Person.parseFrom(rebyte);
                System.out.println(person2.getId()+","+person2.getName() + ", " + person2.getEmail());
                List<PersonProbuf.Person.PhoneNumber> lstPhones = person2.getPhoneList();
                for(PersonProbuf.Person.PhoneNumber phoneNumber : lstPhones) {
                System.out.println(phoneNumber.getNumber());

                }

            }

        }

        catch(Exception s){
            System.out.print(s);
        }

    }

}

c#工程文件(不含通信库)  通信库用别的库也是一样的

时间: 2024-10-22 21:14:10

基于networkcomms V3通信框架的c#服务器与java客户端进行通信之Protobuf探讨的相关文章

基于networkcomms V3通信框架的c#服务器与java客户端进行通信探讨

首先说一下networkcomms 通信框架是商业版的,本文也并不提供. 对java不太熟悉,刚刚安装了eclipse,通信只实现了把字符从java客户端传到c#服务器,服务器收到消息后,返回一个字符消息给java客户端,java客户端显示收到的消息. 服务器端基于networkcomms V3 C#通信框架. 服务器端代码: using System; using System.Collections.Generic; using System.ComponentModel; using Sy

基于NetworkComms V3 使用二进制数据通信

如果客户端和服务端都是C#语言,可以使用 NetworkComms V3 框架自带的,包装的protobuf序列化方式,或者BinaryFormater的方式序列化,都很方便. 刚才和朋友探讨基于networkComms V3与其他语言通信,客户端和服务器端之间传递二进制数组. 本例实现了C#客户端与服务器端传递二进制数据,以此模仿与其他语言的通信 服务器端代码: using System; using System.Collections.Generic; using System.Compo

C++服务器与java进行socket通信案例

分类: [java]2012-10-08 12:03 14539人阅读 评论(46) 收藏 举报 注:本代码版权所有!!!转载时请声明源地址:http://blog.csdn.net/nuptboyzhb/article/details/8047619 你可以学习,分享,修改,教学等.但是不得用于商业目的.目前已经发现互联网上大量与本文完全相同的文章,但是却把作者信息删除的干干净净,并且据为己有,打上某培训机构的广告!实属可恶! 最新消息:项目成品连接:http://blog.csdn.net/

NetworkComms c#通信框架与Java的Netty框架通信 解决粘包问题

上次写了一篇文章  基于networkcomms V3通信框架的c#服务器与java客户端进行通信之Protobuf探讨 其中没有解决粘包问题,抛砖引玉,文章得到了失足程序员 老师的点评,并给出了解决方案:[最多评论]java netty socket库和自定义C#socket库利用protobuf进行通信完整实例(10/591) » 于是马上开始学习,并把c#服务器端换成了我比较熟悉的networkcomms v3 c#通信框架(商业版,本文并不提供) ,以方便与已经存在的系统进行整合. 客户

NetworkComms V3 使用Json序列化器进行网络通信

刚才在网上闲逛,偶然看到一篇文章 C#(服务器)与Java(客户端)通过Socket传递对象 网址是:http://www.cnblogs.com/iyangyuan/archive/2012/12/23/2829712.html#3140522 其中提到了 C#与java如通过传递对象通信的问题 摘引如下: 通信关键: C#和java用Socket通信,发送数据和接收数据可以统一采用UTF-8编码,经过测试,使用UTF-8编码可以成功传递对象. 对于Socket技术,发送数据之前,一般将字符串

HP-SOCKET TCP/UDP通信框架库解析

项目概述: HP-SOCKET是一套通用TCP/UDP通信框架,包括服务器.客户端.Agent组件:其目标是提供高性能.通用性.简易性.可扩展.可定制: 鉴于此,其仅实现基本的通用框架通信.数据收发功能,供上层应用直接简单使用的接口实现:而对于数据包完整性和协议解析等未处理, 也就意味着需要应用层自己处理一些数据包构造或解析等操作: 事实上目前只能支持windows平台: 1. 对于TCP通信模式下:服务器端和Agent均采用的是异步IO模型中的完成端口模型,客户端采用的是就绪IO通告模型中的W

成熟的C#网络通信框架介绍——ESFramework通信框架

ESFramework通信框架是一套性能卓越.稳定可靠.强大易用的跨平台C#网络通信框架,支持应用服务器集群.其内置了消息的收发与自定义处理(支持同步/异步模型).消息广播.P2P通道.文件传送(支持断点续传).心跳检测.断线重连.登录验证.在线用户管理.好友与群组管理.性能诊断等功能.基于ESFramework通信框架,您可以方便快捷地开发出各种优秀的网络通信应用.此外,我们在长期实践中所积累的丰富经验,更将成为您强大的技术保障,从开发到上线直至后续运维,全程为您保驾护航,让您高枕无忧.具体而

NetworkComms V3 基础知识1

Networkcomms 是一款C# 语言编写的TCP/UDP通信框架  作者是英国人  目前已经开源  开源地址是:https://github.com/MarcFletcher/NetworkComms.Net networkcomms通讯框架使用简单方便,性能稳定. 从github上下载到源码后,需要Visual studio安装nuget 加载相关DLL. networkcomms默认使用protobuf进行数据的序列化. 服务器开始监听: Connection.StartListeni

搭建QQ聊天通信的程序:(1)基于 networkcomms.net 创建一个WPF聊天客户端服务器应用程序 (1)

搭建QQ聊天通信的程序:(1)基于 networkcomms.net 创建一个WPF聊天客户端服务器应用程序 原文地址(英文):http://www.networkcomms.net/creating-a-wpf-chat-client-server-application/ 注意:本教程是相当广泛的,如果你是在短请也看到我们的东西 开始和 如何在几分钟内创建一个客户端服务器应用程序教程. 注2:本例中包括,明显延长进一步证明功能,在包中包含的示例 包下载. 在我们开始之前确保您已经安装了Vis