[英]c++ boost asio | sync write to async read | unable to receive correct data in 2nd read
介紹:
我正在嘗試使用c ++和boost :: asio制作服務器/客戶端應用程序,我還試圖通過連續的異步讀取使另一端收到的同步寫入。 例如,我的服務器異步讀取固定字節長度的數據流,然后移至客戶端從同步寫入發送的下一個字節。
問題:
在連續異步讀取中,第一個流字節被正確讀取,但是當它繼續進行下一個異步讀取時,我期望從另一端以相同的字節長度發送一些內容,但這是垃圾,或者無法將其轉換為有價值的數據。
編碼:
private:
static const int MAX_MTU = 1500; //Ethernet Maximum Transfer UNIT (MTU)...
static const int TRASH_CAN = 100; //Amount to substract from the MAX_MTU to make room for basic packet structure elements.
static const int BUFFER_SIZE = MAX_MTU - TRASH_CAN;
boost::mutex mutex;
typedef char* data_bytes;
std::list<data_bytes> data;
private:
tcp::socket socket_;
boost::asio::io_service& io_service_;
moqane::tcp_packet *packet_;
// CTOR for the incoming connection from a client to the server
public: tcp_session(boost::asio::io_service& io_service)
: io_service_(io_service),
socket_(io_service),
packet_(new moqane::tcp_packet())
{
// ......
}
// CTOR for the outgoing clinet connection to the server...
public: tcp_session(boost::asio::io_service& io_service, tcp::resolver::iterator endpoint_iterator)
: io_service_(io_service),
socket_(io_service),
packet_(new moqane::tcp_packet())
{
boost::asio::async_connect(socket_,
endpoint_iterator,
boost::bind(&tcp_session::connect_to_server_hndlr,
this,
boost::asio::placeholders::error)
);
}
tcp::socket& socket()
{
return socket_;
}
public:
void read_header()
{
read_packet(packet_->HEADER_LENGTH,
boost::bind(
&moqane::tcp_session::read_header_hndlr,
shared_from_this(),
packet_->HEADER_LENGTH,
boost::asio::placeholders::error)
);
}
private:
void connect_to_server_hndlr(const boost::system::error_code& error)
{
if (!error)
{
read_header();
}
else
{
// TODO: fire the error event...
}
}
private:
template <class T>
void read_packet(int packet_length, T handler)
{
/*
Packet Structure: (Mohamed Tarek (moqane))
==============================================================================================
HEADER: could be a 3 or 4 bytes that give enough information to the endpoint on how to receive
those bytes.
SIZE : A 4 byte-length number that tell the endpoint how much data in bytes ar comming.
ex: 0340 which should tell us that the incoming data are 340 bytes, so we will not
receive more or less than that.
DATA : the incoming valuable information that we want to receive in the first place.
---------------------------------------------
| | | |
| HEADER | SIZE | DATA... | ----> PACKET
| 3b | 4b | N/A b |
----------------------------------------------
==============================================================================================
*/
if (data.size() > 0)
{
data.clear();
}
char d[moqane::tcp_session::BUFFER_SIZE];
data.push_back(d);
boost::asio::async_read(socket_,
boost::asio::buffer(data.back(), packet_length),
handler
);
}
private:
void write_packet(char* data_bytes)
{
boost::asio::write(socket_, boost::asio::buffer(data_bytes, sizeof(data_bytes)));
}
private:
void write_packet_hndlr(const boost::system::error_code& error)
{
if (!error)
{
}
else
{
}
}
private:
void read_header_hndlr(int packet_length, const boost::system::error_code& error)
{
if (!error)
{
// convert bytes to wxstring
// wxString s = moqane::wx2string::To_wxString(packet_->DATA(), packet_->HEADER_LENGTH());
// convert our bytes to string
std::string header(data.back(), packet_length);
if (packet_->is_header(header))
{
// read the SIZE packet
read_packet(packet_->SIZE_LENGTH,
boost::bind(
&moqane::tcp_session::read_size_hndlr,
shared_from_this(),
packet_->SIZE_LENGTH,
header,
"",
boost::asio::placeholders::error)
);
}
else
{
// reread the HEADER packet if it's not a valid header
read_header();
}
}
else
{
// TODO: fire the error event...
}
}
private:
void read_size_hndlr(int packet_length, std::string header, std::string info, const boost::system::error_code& error)
{
if (!error)
{
std::string str_length(data.back(), packet_length);
int next_packet_length = moqane::number2string::ToInt(str_length);
if (next_packet_length > 0)
{
if (header == packet_->HEADER_STRING)
{
read_packet(next_packet_length,
boost::bind(
&moqane::tcp_session::read_STRING_hndlr,
shared_from_this(),
next_packet_length,
boost::asio::placeholders::error)
);
}
else if (header == packet_->HEADER_COMMAND)
{
}
else
{
// reread the HEADER packet if it's not a valid header
read_header();
}
}
else
{
// reread the HEADER packet if it's not a valid size
read_header();
}
}
else
{
// TODO: fire the error event...
}
}
private:
void read_STRING_hndlr(int packet_length, const boost::system::error_code& error)
{
std::string std_str(data.back(), packet_length);
std::string v = "";
}
public:
void write_STRING(char* string_data)
{
boost::mutex::scoped_lock lock(mutex);
{
write_packet(moqane::number2string::To_CharArray("STR"));
write_packet(moqane::number2string::To_CharArray("xxx1"));
write_packet(moqane::number2string::To_CharArray("a"));
}
}
};
我懷疑問題出在read_packet
char d[moqane::tcp_session::BUFFER_SIZE];
data.push_back(d);
boost::asio::async_read(socket_,
boost::asio::buffer(data.back(), packet_length),
handler
);
這是在局部變量中創建緩沖區d。 然后,將指向d的指針推入data
,然后將其用於形成async_read的緩沖區。 然后,您離開該功能。 這將導致數組被破壞,並帶有多個懸空指針,包括async_read。
我建議為標題創建緩沖區,該緩沖區的名稱類似於“ header”,應作為類的一部分。 我不確定您是否也需要單獨的data
向量。
現在已解決,主要問題是在發送時構造緩沖區時出現錯誤的packet_length
。 因為我得到的是sizeof()
的長度,根據我的處理器體系結構,該長度總是返回4。 所以我現在使用以下函數獲取char *的長度。
public:
static int CharArray_Length(char* somedata)
{
std::list<char> l;
while(*somedata != 0)
l.push_back(*somedata++);
// If you want to add a terminating NULL character
// in your list, uncomment the following statement:
// l.push_back(0);
return l.size();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.