【发布时间】:2015-05-22 07:45:27
【问题描述】:
我已从 boost 的 chat_server 示例中获取代码。
enum eTransactionType{
eBuy=0,
eSell=1
};
struct stOrderPacket{
int ID;
int MarketID;
char m_strSignalName[22];
char m_strTradeSymbol[22];
int m_iQty;
float m_fPrice;
eTransactionType m_eTransactionType;
};
stOrderPacket是TCP客户端和TCPServer共享的结构。
class chat_message
{
public:
enum { max_body_length = sizeof(stOrderPacket) };
chat_message()
: body_length_(0)
{
}
const char* data() const
{
return data_;
}
char* data()
{
return data_;
}
size_t length() const
{
return body_length_;
}
void SetData(char* msg, int len)
{
memset(data_,0x00,len);memcpy(data_,msg,len);
}
void SetOrderParams(stOrderPacket a_stOrderParams);
size_t body_length() const
{
return body_length_;
}
void ClearPacket()
{
memset(data_,0x00,max_body_length);
}
void body_length(size_t length);
private:
char data_[sizeof(stOrderPacket)];
size_t body_length_;
};
chat_message 类是一个保存要写入或读取的消息的类,数据存储在一个大小等于结构 stOrderPacket 大小的字符数组中。
class chat_session{
void start()
{
boost::asio::async_read(socket_,boost::asio::buffer(read_msg_.data(),sizeof(stOrderPacket)),
boost::bind(&chat_session::handle_read_body,shared_from_this(),placeholders::error, placeholders::bytes_transferred()));
}
chat_session 类中的上述函数启动与已连接客户端的会话。
void handle_read_body(const boost::system::error_code& error,std::size_t bytes_transferred)
{
if (0!=error)
{
// handle Close connection.
return;
}
/// stub for parsing the packet
memcpy(&m_stOrderPacket,&m_pvBuffer,sizeof(m_stOrderPacket));
read_msg_.ClearPacket();
boost::asio::async_read(
socket_, buffer(read_msg_.data(),sizeof(structs::stOrderParameters)),
boost::bind(&chat_session::handle_read_body,shared_from_this(),placeholders::error,placeholders::bytes_transferred()));
}
};
客户端发送的数据包如下:
ID | MarketID | Symbol | SignalName | TradeType | Qty | EntryPrice |
| 3021 | 1030320 | RELIANCEEQ | MU_30_INLE_4097_3 | Long | 285 | 1121.1 |
| 3022 | 1030321 | RELIANCEEQ | MU_30_INLE_4097_3 | Long | 178 | 1121 |
| 3038 | 1030505 | RELIANCEEQ | AS_15_SE_53 | Short | 340
| 1116.95 |
但是从 read_msgs_.data 读取的值,当 memcopy 到结构 stOrderPacket 时,是以这样的方式接收的:
a) 第一个数据包是正确的
b) 在第二个数据包中,前 4 个字节是垃圾值,然后我能够将 ID 的值设为 3022,我知道 cz 这个值已分配给 stOrderPacket.MarketID。
c) 第三个值可以从 0+2* sizeof(int) 的索引中正确读取
所以基本上对于每个接收到的数据包,开始 (n-1)*4 字节首先是垃圾,然后信息开始。 此外,所有 3 个数据包的 bytes_transferred 的值都是 64。
注意:我在 x86_64 架构的 CentOS 7 上运行此代码。
如果有人可以,请帮忙。
【问题讨论】:
-
您应该继续累积数据,直到收到正文的所有字节。您可以在要传输的主体字节前面加上一个 int(4 字节)来表示主体大小。其他方法是使用某种分隔符来标记数据体的结尾。为此,您可以使用 async_read_unitil。检查这个 www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/reference/async_read_until.html。
-
boost::asio::async_read()函数有以下限制:程序必须确保流不执行其他读取操作(例如 async_read、流的 async_read_some 函数或执行的任何其他组合操作读取)直到此操作完成。 -
您的
handle_read_body函数无法处理接收到的字节数不等于协议数据单元大小的情况!您可以处理这些情况,也可以使用async_read的变体来读取您需要的内容 (async_read_until),但您必须在某个地方实现协议!
标签: c++ sockets boost tcp boost-asio