Sample for CodedInputStream in C#

2,091 views
Skip to first unread message

Stephen LABBE

unread,
Feb 25, 2016, 12:41:35 PM2/25/16
to Protocol Buffers
Hi,

I try to code a sample about protocol buffer over tcp.
I launch a TCPListener and a TCPClient.

I send with the TCP client and CodedOutputStream a message with some parameters.

But when I try to decode the message with CodedInputStream, I just have the first parameter of my message.
And the EmbeddedMessage is null

Could you explain to me how to decode the entire message ?

This is my listener code :
public static void ListenerProto(string ip, int port) {
            TcpListener server = null;
            try {
                Console.WriteLine();

                IPAddress localAddr = IPAddress.Parse(ip);

                // TcpListener server = new TcpListener(port);
                server = new TcpListener(localAddr, port);

                // Start listening for client requests.
                server.Start();

                // Buffer for reading data
                byte[] bytes = new byte[10000];

                // Enter the listening loop.
                while (true) {
                    Console.WriteLine("Waiting for a connection... ");

                    // Perform a blocking call to accept requests.
                    // You could also user server.AcceptSocket() here.
                    TcpClient client = server.AcceptTcpClient();
                    Console.WriteLine("Connected!");

                    // Get a stream object for reading and writing
                    NetworkStream stream = client.GetStream();

                    CodedInputStream cod = new CodedInputStream(stream);
                 
                    var tcpMessage = TCPMessage.Parser.ParseFrom(cod);

                    // Shutdown and end connection
                    client.Close();
                }
            }
            catch (SocketException e) {
                Console.WriteLine($"SocketException: {e}");
            }
            finally {
                // Stop listening for new clients.
                server?.Stop();
            }
        }

This is my send code
public static void ClientProto(string ipServer, int port, TCPMessage message) {
            try {
                // Create a TcpClient.
                // Note, for this client to work you need to have a TcpServer 
                // connected to the same address as specified by the server, port
                // combination.
                TcpClient client = new TcpClient(ipServer, port);

                //Create stream
                var stream = client.GetStream();

                //Create Coded output stream to send data over the tcp client
                CodedOutputStream cod = new CodedOutputStream(stream);

                // Send the message to the connected TcpServer. 
                //message.WriteTo(stream);
                var calculateSize = message.CalculateSize();

                message.WriteTo(cod);

                //Write message in tb
                Console.WriteLine($"Sent: {message}");

                // Close everything.
                stream.Close();
                client.Close();
            }
            catch (ArgumentNullException e) {
                Console.WriteLine($"ArgumentNullException: {e}");
            }
            catch (SocketException e) {
                Console.WriteLine($"SocketException: {e}");
            }
        }

And finaly that is my proto message (simplify):
syntax = "proto3";

message TCPMessage {
enum Type {
Add = 0;
Remove = 1;
Select = 2;
Update = 3;
}
message Parameter {
string name = 1;
string value = 2;
}
message EmbeddedMessage {
string id = 1;
Type type = 2;
repeated Parameter parameters = 3;
}
Type commande = 1;
EmbeddedMessage type = 2;
}


Jon Skeet

unread,
Feb 26, 2016, 7:58:16 AM2/26/16
to Protocol Buffers
Hi Stephen,

It's quite possible that all you're missing is a cod.Flush() call in the sending code.
Looking at the documentation, I think we're missing the flush call there too, which suggests it's far too easy to do.
I've raised https://github.com/google/protobuf/issues/1282 to make sure we don't miss this.

Jon

Jon Skeet

unread,
Feb 29, 2016, 6:47:05 AM2/29/16
to Protocol Buffers
I've just had another look in the docs, and there isn't a flush missing as it happens - but the reason is slightly subtle.

Your code manually creates a CodedOutputStream and writes to it without flushing.
The documentation sample creates a FileStream and calls the IMessage.WriteTo(Stream) extension method - which does flush.

So you could change your code to just use:

message.WriteTo(stream)

instead - remove all mention of CodedOutputStream in your code.

That said, making all of this simpler in cases where you are using CodedOutputStream feels like a good idea. I've got a pull request which wouldn't actually fix your current code, but which makes it easier to use a CodedOutputStream with a using statement.

Jon
Reply all
Reply to author
Forward
0 new messages