问题描述
当我通过套接字通信发送一个protobuf变量recv end我试图显示protobuf的字符串变量我得到分割在这个剩余的数据类型,除了字符串,他们工作正常但字符串变量case我得到了如何
我在Protobuf中创建了一个example.proto字符串数据类型sementation错误,除了我们有任何其他数据类型存储字符串数据类型。是有
我编译example.proto与protoc编译器(protoc example.proto --cpp_out)
它创建两个文件两个文件example.pb.h,example.pb.cc
使用这些文件我创建一个test_server.cpp和test_client.cpp
并编译它。但是在两个程序运行的时候,我在recv端发送了一个protobuf变量,由于尝试显示字符串变量,它给出了分段错误。
我如何解决这个问题?
<$ p>
包数据;
message star
{可选字符串名称= 1; }
server.cpp
#include< iostream>
#include< sys / types.h>
#include< sys / socket.h>
#include< netinet / in.h>
#include< strings.h>
#include< string.h>
#include< arpa / inet.h>
#includeexample.pb.h
#includeexample.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<<Bind FAIL\\\
;
else
cout<<Bind Success\ n;
if((csd = accept(sd,(struct sockaddr *)& cli,& s))== - 1)
cout< n。
else
cout<<ConnectioN Accept Success\;
star pkt;
recv(csd,& pkt,sizeof(pkt),0);
cout<<\t String Name:<< pkt.name<< endl; //这里只有我得到分割
close(sd);
close(csd);
}
cpp
#include< iostream&
#include< sys / types.h>
#include< sys / socket.h>
#include< netinet / in.h>
#include< strings.h>
#include< string.h>
#include< arpa / inet.h>
#includeexample.pb.h
#includeexample.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<<connect FAIL\\\
;
else
cout<<connect Success\\\
;
star pkt;
pkt.set_name(Pratap);
cout<<发送数据而无需使用另一个变量.... \\\
;
send(sd,& pkt,sizeof(pkt),MSG_CONFIRM);
close(sd);
}
您的问题在这里:
star pkt;
recv(csd,& pkt,sizeof(pkt),0);
,其中:
star pkt;
pkt.set_name(Pratap);
cout<<发送数据而无需使用另一个变量.... \\\
;
send(sd,& pkt,sizeof(pkt),MSG_CONFIRM);
您不能接收/发送明星
实例直接从/到protobuf有线格式首先没有/序列化。请查看类。 p>
最好的方法是首先以固定格式发送序列化消息的长度(例如在网络字节中 uint32_t
订购)。然后接收器可以先读取这个,并在接收之前发送的序列化消息之前分配适当大小的缓冲区。
UPDATE: br>
尝试s.th.像这样:
Sender.cpp
star pbMsgObj;
pbMsgObj.set_name(Pratap);
std :: string pkt;
pbMsgObj.SerializeToString(& pkt); //将消息对象序列化为
// protobuf有线格式。
uint32_t msgLength = pkt.size();
uint32_t sndMsgLength = htonl(msg_length); //确保网络字节顺序
send(sd,& sndMsgLength,sizeof(uint32_t),MSG_CONFIRM); //发送消息长度
send(sd,pkt.c_str(),msgLength,MSG_CONFIRM); //发送邮件数据
Receiver.cpp
star msgObject;
uint32_t msgLength;
recv(csd,& msgLength,sizeof(uint32_t),0); //接收消息长度
msgLength = ntohl(msgLength); //确保主机系统字节顺序
std :: vector< uint8_t> pkt; //分配接收缓冲区
pkt.resize(msgLength,0x00);
recv(csd,&(pkt [0]),msgLength,0); //接收消息数据
std :: string tmp;
tmp.assign(&(pkt [0]),pkt.size()); //将消息数据转换为字符串
msgObject.ParseFromString(tmp); //从
// protobuf wire格式反序列化消息对象。
注意:
/用于各种语言绑定的唯一高效的有线格式是google协议缓冲区的整体点。
为了跳出可能的发送者/接收者模式的位创建原始套接字,您可能会发现是一个有用的框架。反正听好的建议(!):保持消息(有效载荷)格式和发送/ recv行为尽可能分开。
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 sementation How can I over come in Protobuf string datatype sementation 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 thereI 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<iostream>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<strings.h>
#include<string.h>
#include <arpa/inet.h>
#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<<"Bind FAIL\n";
else
cout<<"Bind Success\n";
if((csd=accept(sd,(struct sockaddr *)&cli, &s))==-1)
cout<<"Connection Accept FAIL\n";
else
cout<<"ConnectioN Accept Success\n";
star pkt;
recv(csd,&pkt,sizeof(pkt),0);
cout<<"\t String Name: "<<pkt.name<<endl; //Here only i get segmentation
close(sd);
close(csd);
}
client.cpp
#include<iostream>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<strings.h>
#include<string.h>
#include <arpa/inet.h>
#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<<"connect FAIL\n";
else
cout<<"connect Success\n";
star pkt;
pkt.set_name("Pratap");
cout<<"Send Data without help of another variable....\n";
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 Data without help of another variable....\n";
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<uint8_t> 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.
这篇关于由于PROTOBUF服务器中的字符串数据类型变量而产生segfault,并且通过cvv上的recv端口通过套接字进行clent通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!