我是网络编程的新手。我尝试使用boost序列化发送和接收结构。在服务器端,我使用结构向量来发送信息,在接收方,我不知道如何以合适的方式接收向量并对其进行反序列化。现在,我得到了分段错误。任何帮助都非常感谢。
服务器端:
struct packet{
std::string pos;
int size;
int Lid;
int Tid;
int Qid;
std::string type;
std::string disc;
std::string trunc;
int nframe;
template<typename Archive>
void serialize(Archive&ar, const unsigned int version){
ar & pos;
ar &size;
ar&Lid;
ar&Tid;
ar&Qid;
ar&type;
ar&disc;
ar&trunc;
ar&nframe;
}
};
int main()
{
try
{
boost::asio::io_service io_service;
tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(),50013));
cout<<"Server waiting for connections: ....."<<endl;
//send data to the receiver
for(;;){ //infinite loop(always listening, the session is not closed)
//creates a socket
tcp::socket socket(io_service);
//wait and listen
acceptor.accept(socket);
//prepare message to send back to the client
std::string message="Connection accepted! \n";
boost::system::error_code ignored_error;
//write the message
boost::asio::write(socket, boost::asio::buffer(message),ignored_error);
//open the trace file
char pos[20],type[20],trunc[20],disc[20];
int L,T,Q,size,nframe;
FILE *tracefile;
const char * cpath = path.c_str();
tracefile=fopen(cpath,"r");
fscanf(tracefile,"%s %d %d %d %d %s %s %s %d",pos,&size,&L,&T,&Q,type,disc,trunc,&nframe);
std::vector<packet> sendpacket;
sendpacket.push_back(packet());
string spos(pos);
string stype(type);
string sdisc(disc);
string strunc(trunc);
sendpacket[0].pos=spos;
sendpacket[0].size=size;
sendpacket[0].Lid=L;
sendpacket[0].Tid=T;
sendpacket[0].Qid=Q;
sendpacket[0].type=stype;
sendpacket[0].disc=sdisc;
sendpacket[0].trunc=strunc;
sendpacket[0].nframe=nframe;
cout<<sendpacket[0].pos<<endl;
cout<<sendpacket[0].size<<endl;
socket.send(boost::asio::buffer(sendpacket));
}
}
接收方:
struct packet{
std::string pos;
int size;
int Lid;
int Tid;
int Qid;
std::string type;
std::string disc;
std::string trunc;
int nframe;
};
int main(int argc, char* argv[])
{
//Receive the first packet
std::vector<packet> receivedpacket;
//data received from the server
socket.receive(boost::asio::buffer(receivedpacket));
cout<<receivedpacket[0].pos<<endl;
cout<<receivedpacket[0].size<<endl;
cout<<receivedpacket[0].Lid<<endl;
cout<<receivedpacket[0].Tid<<endl;
}
答案 0 :(得分:0)
我使用boost库示例中的序列化示例解决了问题:http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/examples.html
现在,我能够使用async_write和async_read发送和接收结构。当我发送一个数据包时效果很好但是如果我开始按顺序发送几个数据包,则不会在客户端收到数据包并给我一个&#34;无效的参数&#34;信息。
这就像写入和读取过程不同步或我应该使用某种类型的信令通知服务器客户端已成功读取所有信息并可以发送下一个数据包?
感谢您的帮助!
服务器端:
//while(!feof(tracefile)){
fscanf(tracefile,"%s %d %d %d %d %s %s %s %d",pos,&size,&L,&T,&Q,type,disc,trunc,&nframe);
string spos(pos);
string sdisc(disc);
string stype(type);
string strunc(trunc);
//create the data to be sent to the client
pckt.pos=spos;
pckt.size=size;
pckt.Lid=L;
pckt.Tid=T;
pckt.Qid=Q;
pckt.type=stype;
pckt.disc=sdisc;
pckt.trunc=strunc;
pckt.nframe=nframe;
vpacket.push_back(pckt);
//send the packet to the client. The connection::async_write() function will automatically serialize the data structure for us
conn->sendpacket(vpacket,boost::bind(&server::handle_write,this, boost::asio::placeholders::error, conn));
cout<<"packet sent"<<endl;
//}
SendPacket功能:
/// Asynchronously write a data structure to the socket.
template <typename T, typename Handler>
void sendpacket(const T& t, Handler handler)
{
// Serialize the data first so we know how large it is.
std::ostringstream archive_stream;
boost::archive::text_oarchive archive(archive_stream);
archive << t;
outbound_data_ = archive_stream.str();
// Format the header.
std::ostringstream header_stream;
header_stream << std::setw(header_length)
<< std::hex << outbound_data_.size();
if (!header_stream || header_stream.str().size() != header_length)
{
// Something went wrong, inform the caller.
boost::system::error_code error(boost::asio::error::invalid_argument);
socket_.get_io_service().post(boost::bind(handler, error));
return;
}
outbound_header_ = header_stream.str();
// Write the serialized data to the socket. We use "gather-write" to send
// both the header and the data in a single write operation.
std::vector<boost::asio::const_buffer> buffers;
buffers.push_back(boost::asio::buffer(outbound_header_));
buffers.push_back(boost::asio::buffer(outbound_data_));
boost::asio::async_write(socket_,buffers,handler);
}
接收方:
//Start operation to read the list
// of stocks. The connection::async_read() function will automatically
// decode the data that is read from the underlying socket.
int nlines; //number of lines tracefile
//for(int j=0;j<nlines;j++){
connection_.receivepacket(rpacket,
boost::bind(&client::handle_read, this,
boost::asio::placeholders::error));
//}
ReceivePacket功能:
/// Asynchronously read a data structure from the socket.
template <typename T, typename Handler>
void receivepacket(T& t, Handler handler)
{
// Issue a read operation to read exactly the number of bytes in a header.
void (connection::*f)(
const boost::system::error_code&,
T&, boost::tuple<Handler>)
= &connection::handle_read_header<T, Handler>;
boost::asio::async_read(socket_, boost::asio::buffer(inbound_header_),
boost::bind(f,
this, boost::asio::placeholders::error, boost::ref(t),
boost::make_tuple(handler)));
}
/// Handle a completed read of a message header. The handler is passed using
/// a tuple since boost::bind seems to have trouble binding a function object
/// created using boost::bind as a parameter.
template <typename T, typename Handler>
void handle_read_header(const boost::system::error_code& e,
T& t, boost::tuple<Handler> handler)
{
if (e)
{
boost::get<0>(handler)(e);
}
else
{
// Determine the length of the serialized data.
std::istringstream is(std::string(inbound_header_, header_length));
std::size_t inbound_data_size = 0;
if (!(is >> std::hex >> inbound_data_size))
{
// Header doesn't seem to be valid. Inform the caller.
boost::system::error_code error(boost::asio::error::invalid_argument);
boost::get<0>(handler)(error);
return;
}
// Start an asynchronous call to receive the data.
inbound_data_.resize(inbound_data_size);
void (connection::*f)(
const boost::system::error_code&,
T&, boost::tuple<Handler>)
= &connection::handle_read_data<T, Handler>;
boost::asio::async_read(socket_, boost::asio::buffer(inbound_data_),
boost::bind(f, this,
boost::asio::placeholders::error, boost::ref(t), handler));
}
}
/// Handle a completed read of message data.
template <typename T, typename Handler>
void handle_read_data(const boost::system::error_code& e,
T& t, boost::tuple<Handler> handler)
{
if (e)
{
boost::get<0>(handler)(e);
}
else
{
// Extract the data structure from the data just received.
try
{
std::string archive_data(&inbound_data_[0], inbound_data_.size());
std::istringstream archive_stream(archive_data);
boost::archive::text_iarchive archive(archive_stream);
archive >> t;
}
catch (std::exception& e)
{
// Unable to decode data.
boost::system::error_code error(boost::asio::error::invalid_argument);
boost::get<0>(handler)(error);
return;
}
// Inform caller that data has been received ok.
boost::get<0>(handler)(e);
}
}
private:
/// The underlying socket.
boost::asio::ip::tcp::socket socket_;
/// The size of a fixed length header.
enum { header_length = 8 };
/// Holds an outbound header.
std::string outbound_header_;
/// Holds the outbound data.
std::string outbound_data_;
/// Holds an inbound header.
char inbound_header_[header_length];
/// Holds the inbound data.
std::vector<char> inbound_data_;