test
test

Reputation: 75

c# client connect java netty server using protobuf

server got an error: Protocol message tag had invalid wire type. Is there my c# code need serialize Person object?

maven configure

<dependencies>
    <dependency>
        <groupId>io.netty</groupId>
        <artifactId>netty-all</artifactId>
        <version>4.1.12.Final</version>
    </dependency>

    <dependency>
        <groupId>com.google.protobuf</groupId>
        <artifactId>protobuf-java</artifactId>
        <version>3.3.1</version>
    </dependency>

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>3.8.1</version>
        <scope>test</scope>
    </dependency>
</dependencies>

server code

public class AppServer {
   public void startSocket(int port) throws Exception {
    EventLoopGroup bossGroup = new NioEventLoopGroup();
    EventLoopGroup workerGroup = new NioEventLoopGroup();

    try {
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 100).handler(new LoggingHandler(LogLevel.INFO))
                .childHandler(new ChannelInitializer<SocketChannel>() {

                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new ProtobufVarint32FrameDecoder());
                        ch.pipeline().addLast(new ProtobufDecoder(Person.getDefaultInstance()));
                        ch.pipeline().addLast(new ProtobufServerHandler());

                    }
                });
        ChannelFuture future = serverBootstrap.bind(port).sync();
        System.out.println("Server Starting.");
        future.channel().closeFuture().sync();
    } finally {
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }
}

public static class ProtobufServerHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        Person person = (Person) msg;
        System.out.println(person);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        // TODO Auto-generated method stub
        super.channelReadComplete(ctx);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        Person john = Person.newBuilder().setId(1234).setName("John Doe").setEmail("[email protected]")
                .addPhones(Person.PhoneNumber.newBuilder().setNumber("555-4321").setType(Person.PhoneType.HOME))
                .build();
        ctx.writeAndFlush(john);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
    }
}

public static void main(String[] args) throws Exception {
    int port = 8081;

    if(args != null && args.length > 0){
        port = Integer.valueOf(args[0]);
    }

    new AppServer().startSocket(port);
  }
}

C# client code

namespace proto
 {
class Program
{
    static void Main(string[] args)
    {
        var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        socket.Connect("127.0.0.1", 8081);
        Console.WriteLine("===========connect to server===========");

        var buffer = new byte[1024 * 1024];
        socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket);

        SendMessage(socket);

        if (socket.Connected)
        {
            socket.Shutdown(SocketShutdown.Both);
        }


        Console.Read();
    }

            private static void SendMessage(Socket socket)
    {
        var sam = new Person();
        sam.Name = "John Doe";
        sam.Email = "[email protected]";
        sam.Id = 1234;
        sam.Phones.Add(new Person.Types.PhoneNumber()
        {
            Number = "555-4321",
            Type = Person.Types.PhoneType.Home
        });

        if (socket.Connected)
        {
            var stream = new MemoryStream();
            var aa = sam.ToByteArray();

            socket.BeginSend(aa, 0, aa.Length, SocketFlags.None, null, null);                
        }
    }

    private static void ReceiveMessage(IAsyncResult ar)
    {
        Console.WriteLine("===========receive from server===========");
        Console.WriteLine(ar);
    }
}
  }

.proto file

// See README.txt for information and build instructions.
  //
  // Note: START and END tags are used in comments to define sections used in
  // tutorials.  They are not part of the syntax for Protocol Buffers.
  //
  // To get an in-depth walkthrough of this file and the related examples, see:
  // https://developers.google.com/protocol-buffers/docs/tutorials

  // [START declaration]
  syntax = "proto3";
  package tutorial;
  // [END declaration]

  // [START java_declaration]
  option java_package = "com.example.tutorial";
  option java_outer_classname = "AddressBookProtos";
  // [END java_declaration]

  // [START csharp_declaration]
  option csharp_namespace = "Google.Protobuf.Examples.AddressBook";
  // [END csharp_declaration]

  // [START messages]
  message Person {
    string name = 1;
    int32 id = 2;  // Unique ID number for this person.
    string email = 3;

    enum PhoneType {
      MOBILE = 0;
      HOME = 1;
      WORK = 2;
    }

    message PhoneNumber {
      string number = 1;
      PhoneType type = 2;
    }

    repeated PhoneNumber phones = 4;
  }

  // Our address book file is just one of these.
  message AddressBook {
    repeated Person people = 1;
  }
  // [END messages]

erver got an error: Protocol message tag had invalid wire type. Is there my c# code need serialize Person object?

Upvotes: 1

Views: 1198

Answers (1)

Marc Gravell
Marc Gravell

Reputation: 1063338

Your server code makes mention of a varint-based frame decoder (ProtobufVarint32FrameDecoder) - presumably anticipating a length-prefixed message (frame). However, your client code sends a raw protobuf without any framing mechanism.

I suggest you need to add framing to the client code, via whatever API it exposes for such (if this were protobuf-net, it would be the SerializeWithLengthPrefix method).

Upvotes: 1

Related Questions