|
沙发

楼主 |
发表于 2020-9-5 18:44:30
|
只看该作者
网络数据的压缩和解压缩
玩家发来命令,服务器转发向玩家命令,服务器产生事件,都是以压缩过形式在网络上流通。document封装一条命令/事件,内部操作支持了解缩和解压缩。注:这个一条是相对的,它可能是数条命令合成的一条命令,像send_history后形成的document。
要知道压缩和解压缩大概是怎么个过程首先就要了解document对象几个成员,它大概存储了什么内容。- @compressed_buf:已压缩过数据。这往往是直接从网络上收到的数据。这个构造函数作就是根据网络上收到数据恢复出命令。
- document::document(string_span compressed_buf) :
- compressed_buf_(compressed_buf),
- output_(NULL),
- buffers_(),
- root_(NULL),
- prev_(NULL),
- next_(NULL)
- {
- string_span uncompressed_buf;
- // uncompress_buffer执行解压缩,解压缩后的数据放在从堆中分配出的一块内存
- buffers_.push_back(uncompress_buffer(compressed_buf, &uncompressed_buf));
- output_ = uncompressed_buf.begin();
- const char* cbuf = output_;
- try {
- root_ = new node(*this, NULL, &cbuf);
- } catch(...) {
- delete [] buffers_.front();
- buffers_.clear();
- throw;
- }
- attach_list();
- }
- 至此大概可以总结下各个成员意义
- compressed_buf_:压缩过数据。
- buffers_:数据存储缓冲。它是一个vector,它的[0]存储的是未压缩过数据,[1]存储的是压缩过数据。注意下这两个数据都被从堆中分配,析构时要delete。
- output_:未压缩过数据。
- root_:<尚未理解>
复制代码 程序往往要遍历历史命令,这个遍历是通过把命令组织在一个链表,attach_list()作用就这是把这个命令放入链表。下图是使用的链表结构
send_history会遍历所有历史命令(但它不是通过链表),并在遍历时把所有命令合成一条命令,形成一个新的document- 功能:把历史记录发向sock指定玩家。
- 注:在发送过程中,它会把原有记录合成一条记录,再写回历史容器
- void game::send_history(const network::connection sock) const
- {
- if(history_.empty()) {
- return;
- }
- //we make a new document based on converting to plain text and
- //concatenating the buffers.
- //TODO: Work out how to concentate buffers without decompressing.
- std::string buf;
- for(std::vector<simple_wml::document*>::iterator i = history_.begin();
- i != history_.end(); ++i) {
- // (*i)->output()返回是未压缩过数据
- buf += (*i)->output();
- delete *i;
- }
- try {
- simple_wml::document* doc = new simple_wml::document(buf.c_str(), simple_wml::INIT_STATIC);
- const simple_wml::string_span& data = doc->output_compressed();
- // 压缩
- doc->compress();
- network::send_raw_data(data.begin(), data.size(), sock,"game_history");
- history_.clear();
- history_.push_back(doc);
- } catch (simple_wml::error& e) {
- WRN_CONFIG << __func__ << ": simple_wml error: " << e.message << std::endl;
- }
- }
复制代码 |
|