// My command fbs namespace TcpIpServer; table Command { id:int; name:string; } root_type Command;
~/flatc.exe --cpp command.fbs
#include <Core/Core.h> #include "command_generated.h" using namespace Upp; ...
//a simple Command struct struct Command{ public: int id; String name; Command(int _id, String _name){id = _id; name = _name;} String ToString()const{ String toStr; toStr << "Id: " << id << ", Name: " << name << "\n"; return toStr; } }; struct CommandSerializer{ public: CommandSerializer(const Command& cmd){ flatbuffers::Offset<flatbuffers::String> str1 = builder.CreateString(cmd.name.ToStd()); //First, we create a special flatbuffers object that handle string TcpIpServer::CommandBuilder commandBuilder(builder); //Then we create a commandBuilder (a special object that will construct our Command (the fbs file)) commandBuilder.add_id(cmd.id); //We define value of each parameters of our command commandBuilder.add_name(str1); //We define value of each parameters of our command flatbuffers::Offset<TcpIpServer::Command> freshCommand = commandBuilder.Finish(); //we retrieve our command by telling our commandBuilder we are done with it builder.Finish(freshCommand); //we end the builder of our newly command (named freshCommand) } int GetSize(){return builder.GetSize();} //Return a ptr to our serialized object uint8_t* GetDatasPtr(){return builder.GetBufferPointer();} //Return size of our serialized object private: flatbuffers::FlatBufferBuilder builder; //Builder is used to create everything we want with flatbuffers }; Command CommandDeserializer(uint8_t* datas, int size){ flatbuffers::Verifier verfier(datas,size); //Verifier is used to verify our buffer of data is a valid command if(TcpIpServer::VerifyCommandBuffer(verfier)){ const TcpIpServer::Command* serializedCmd = TcpIpServer::GetCommand(datas); //If our buffer is valid then we retrieve a ptr to the command within this buffer return Command(serializedCmd->id(), String(serializedCmd->name()->c_str())); //then we use our buffer to build our command } throw Exc("Invalide command"); }
#include <Core/Core.h> #include "flatbuffer-command/command_generated.h" using namespace Upp; //a simple Command struct struct Command{ public: int id; String name; Command(int _id, String _name){id = _id; name = _name;} String ToString()const{ String toStr; toStr << "Id: " << id << ", Name: " << name; return toStr; } }; struct CommandSerializer{ public: CommandSerializer(const Command& cmd){ flatbuffers::Offset<flatbuffers::String> str1 = builder.CreateString(cmd.name.ToStd()); //First, we create a special flatbuffers object that handle string TcpIpServer::CommandBuilder commandBuilder(builder); //Then we create a commandBuilder (a special object that will construct our Command (the fbs file)) commandBuilder.add_id(cmd.id); //We define value of each parameters of our command commandBuilder.add_name(str1); //We define value of each parameters of our command flatbuffers::Offset<TcpIpServer::Command> freshCommand = commandBuilder.Finish(); //we retrieve our command by telling our commandBuilder we are done with it builder.Finish(freshCommand); //we end the builder of our newly command (named freshCommand) } int GetSize(){return builder.GetSize();} //Return a ptr to our serialized object uint8_t* GetDatasPtr(){return builder.GetBufferPointer();} //Return size of our serialized object private: flatbuffers::FlatBufferBuilder builder; //Builder is used to create everything we want with flatbuffers }; Command CommandDeserializer(const uint8_t* datas, int size){ flatbuffers::Verifier verfier(datas,size); //Verifier is used to verify our buffer of data is a valid command if(TcpIpServer::VerifyCommandBuffer(verfier)){ const TcpIpServer::Command* serializedCmd = TcpIpServer::GetCommand(datas); //If our buffer is valid then we retrieve a ptr to the command within this buffer return Command(serializedCmd->id(), String(serializedCmd->name()->c_str())); //then we use our buffer to build our command } throw Exc("Invalide command"); } CONSOLE_APP_MAIN { StdLogSetup(LOG_COUT|LOG_FILE); TcpSocket server; if(!server.Listen(3214, 5)) { LOG("Unable to initialize server socket!\n"); SetExitCode(1); return; } LOG("Waiting for requests.."); for(;;) { TcpSocket s; if(s.Accept(server)){ String datas; dword sizeReceived; if(s.Get(&sizeReceived, sizeof(sizeReceived))) datas = s.Timeout(5000).Get(sizeReceived); try{ LOG(CommandDeserializer((uint8_t*)datas.ToStd().c_str(),datas.GetLength())); CommandSerializer cmdValide(Command(0,"Valide")); dword sizeToSend = cmdValide.GetSize(); if(s.Put(&sizeToSend,sizeof(sizeToSend))) s.Timeout(5000).Put(cmdValide.GetDatasPtr(),cmdValide.GetSize()); }catch(Exc& exception){ CommandSerializer cmdInvalide(Command(-1,"Invalide")); dword sizeToSend = cmdInvalide.GetSize(); if(s.Put(&sizeToSend,sizeof(sizeToSend))) s.Timeout(5000).Put(cmdInvalide.GetDatasPtr(),cmdInvalide.GetSize()); } } } }
#include <Core/Core.h> #include "flatbuffer-command/command_generated.h" using namespace Upp; //a simple Command struct struct Command{ public: int id; String name; Command(int _id, String _name){id = _id; name = _name;} String ToString()const{ String toStr; toStr << "Id: " << id << ", Name: " << name ; return toStr; } }; struct CommandSerializer{ public: CommandSerializer(const Command& cmd){ flatbuffers::Offset<flatbuffers::String> str1 = builder.CreateString(cmd.name.ToStd()); //First, we create a special flatbuffers object that handle string TcpIpServer::CommandBuilder commandBuilder(builder); //Then we create a commandBuilder (a special object that will construct our Command (the fbs file)) commandBuilder.add_id(cmd.id); //We define value of each parameters of our command commandBuilder.add_name(str1); //We define value of each parameters of our command flatbuffers::Offset<TcpIpServer::Command> freshCommand = commandBuilder.Finish(); //we retrieve our command by telling our commandBuilder we are done with it builder.Finish(freshCommand); //we end the builder of our newly command (named freshCommand) } int GetSize(){return builder.GetSize();} //Return a ptr to our serialized object uint8_t* GetDatasPtr(){return builder.GetBufferPointer();} //Return size of our serialized object private: flatbuffers::FlatBufferBuilder builder; //Builder is used to create everything we want with flatbuffers }; Command CommandDeserializer(const uint8_t* datas, int size){ flatbuffers::Verifier verfier(datas,size); //Verifier is used to verify our buffer of data is a valid command if(TcpIpServer::VerifyCommandBuffer(verfier)){ const TcpIpServer::Command* serializedCmd = TcpIpServer::GetCommand(datas); //If our buffer is valid then we retrieve a ptr to the command within this buffer return Command(serializedCmd->id(), String(serializedCmd->name()->c_str())); //then we use our buffer to build our command } throw Exc("Invalide command"); } Command SendCommand(const Command& cmd){ TcpSocket s; s.Timeout(600); if(!s.Connect("127.0.0.1", 3214)){ throw Exc("Unable to connect to server!"); } CommandSerializer serializer(cmd); dword sizeToSend = serializer.GetSize(); if(s.Put(&sizeToSend,sizeof(sizeToSend))) s.Timeout(5000).Put(serializer.GetDatasPtr(),serializer.GetSize()); String datas; dword sizeReceived; if(s.Get(&sizeReceived, sizeof(sizeReceived))) datas = s.Timeout(5000).Get(sizeReceived); return CommandDeserializer((const uint8_t*)datas.ToStd().c_str(),datas.GetLength()); } CONSOLE_APP_MAIN{ StdLogSetup(LOG_COUT | LOG_FILE); try{ LOG(SendCommand(Command(3,"Exemple"))); LOG(SendCommand(Command(3,"Exemple2"))); LOG(SendCommand(Command(3,"Exemple3"))); }catch(Exc& exception){ LOG(exception); } }
. however, in my computer for whatever reason (my code seems correct comparing to socketClient/socketServer package) the data is received on server only when I close the client.
int numberByteRead = s.Get(datas, 2048);
int TcpScoket::Get(void *buffer, int len) Reads at most len bytes into buffer, trying to do so at most for specified timeout. Returns the number of bytes actually read.
, I guess adding '\n' to every packet of data is ugly
String data; dword len = data.GetLength(); if(socket.Put(&len, sizeof(dword)) socket.Timeout(30000).Put(~data, len);
Since this is going to be a simple example why don't you just send the size of the data to be transferred first?Indeed it is smart ! Exemple have been udpated.
Let the other side fetch that first, and then call Get() again with the size and timeout in 30 secs.
P.s: And if you are sending binary data over the network, it is in general a good practice to convert it to base64 encoding)I think protobuff do it by himself. I will check this later