When I am sending a protobuf variable through socket communication on recv end I am trying to display the string variable of protobuf I got segmentation in this remaining Data type other than String they are working fine but string variable case I got segmentation How can I over come in Protobuf string datatype segmentation fault other than we have any other data type for store the string data type.
I create a example.proto with in string variable name is there
I am compile example.proto with protoc compiler (protoc example.proto --cpp_out )
it create two files two files example.pb.h, example.pb.cc
By using these files I create a test_server.cpp and test_client.cpp
And compile it. but at the time of both programms runing I sent a protobuf variable on recv side it give segmentation fault due to trying to display string variable.
How can I solve this problem?
example.proto
package data;
message star
{ optional string name=1; }
server.cpp
#include
#include
#include
#include
#include
#include
#include
#include"example.pb.h"
#include"example.pb.cc"
int main()
{
int sd,csd;
sd=socket(AF_INET, SOCK_STREAM,0);
perror("socket");
sockaddr_in ser,cli;
ser.sin_family=AF_INET;
ser.sin_port=htons(7878);
ser.sin_addr.s_addr=inet_addr("X.Y.Z.A");
bzero(ser.sin_zero, 8);
size_t s=16;
if(bind(sd,(struct sockaddr *)&ser, s)==-1)
cout<
else
cout<
if((csd=accept(sd,(struct sockaddr *)&cli, &s))==-1)
cout<
else
cout<
star pkt;
recv(csd,&pkt,sizeof(pkt),0);
cout<
close(sd);
close(csd);
}
client.cpp
#include
#include
#include
#include
#include
#include
#include
#include"example.pb.h"
#include"example.pb.cc"
int main()
{
int sd;
sd=socket(AF_INET, SOCK_STREAM,0);
perror("socket");
sockaddr_in ser;
ser.sin_family=AF_INET;
ser.sin_port=htons(7878);
ser.sin_addr.s_addr=inet_addr("X.Y.Z.A");
bzero(ser.sin_zero, 8);
if(connect(sd,(struct sockaddr *)&ser, 16)==-1)
cout<
else
cout<
star pkt;
pkt.set_name("Pratap");
cout<
send(sd,&pkt,sizeof(pkt) ,MSG_CONFIRM);
close(sd);
}
解决方案
Your problem is here:
star pkt;
recv(csd,&pkt,sizeof(pkt),0);
and here:
star pkt;
pkt.set_name("Pratap");
cout<
send(sd,&pkt,sizeof(pkt) ,MSG_CONFIRM);
You can't receive/send the star instance directly without de/serializing it from/to protobuf wire format first. Have a look at the ParseFrom SerializeTo methods of the protobuf::MessageLite class.
The best way is to send the length of the serialized message first in a fixed format (e.g. a uint32_t in network byte order). Then the receiver can read this first and allocate a buffer of the appropriate size before receiving the serialized message that is send afterwards.
UPDATE:
Try s.th. like this:
Sender.cpp
star pbMsgObj;
pbMsgObj.set_name("Pratap");
std::string pkt;
pbMsgObj.SerializeToString(&pkt); // Serialize the message object to
// protobuf wire format.
uint32_t msgLength = pkt.size();
uint32_t sndMsgLength = htonl(msg_length); // Ensure network byte order
send(sd,&sndMsgLength ,sizeof(uint32_t) ,MSG_CONFIRM); // Send the message length
send(sd,pkt.c_str() ,msgLength ,MSG_CONFIRM); // Send the message data
Receiver.cpp
star msgObject;
uint32_t msgLength;
recv(csd,&msgLength,sizeof(uint32_t),0); // Receive the message length
msgLength = ntohl(msgLength); // Ensure host system byte order
std::vector pkt; // Allocate a receive buffer
pkt.resize(msgLength,0x00);
recv(csd,&(pkt[0]),msgLength,0); // Receive the message data
std::string tmp;
tmp.assign(&(pkt[0]),pkt.size()); // Convert message data to a string
msgObject.ParseFromString(tmp); // Deserialize the message object from
// protobuf wire format.
NOTE:
De-/Serializing from/to a unique, efficient wire format used with various language bindings is the whole point of google protocol buffers.
For twiddling out the bits of possible sender/receiver patterns, instead of creating 'raw' sockets you might find 0MQ being a useful framework. Anyway listen to good advice(!): Keep message (payload) format and send/recv behavior as separate as possible.