SDL中文论坛

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 5107|回复: 3
打印 上一主题 下一主题

[network] 服务器编程

[复制链接]

149

主题

331

帖子

2445

积分

版主

Rank: 7Rank: 7Rank: 7

积分
2445
跳转到指定楼层
楼主
发表于 2020-9-5 18:43:28 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
server::run()一些注释
1、network::accept_connect是非阻塞等待。
2、string_ip:本机连接时是127.0.0.1。
3、reason:空。指示accept_connect过程没有发生错误。
4、sock:为此个客户端服务的sock。

处理登陆
登陆分两个步骤,分别对应两个包:(process_login处理这两个包)
1、[version]version="0.1.4"[/version]
2、[login]selective_ping="1"username="ancientcc2"[/login]

处理游戏大厅
游戏大厅触发的动作:(process_data_lobby处理这些个动作)
创建:[create_game]name="ancientcc2xxxxx"[/create_game]
第二个消息
"#textdomain wesnoth-multiplayer
description=_ "These caves were once the lair of Chak'kso Ney'yks, a legendary Elder Basilisk. The petrified forms of his victims remain as monuments to his savage power."
experience_modifier="70"
id="multiplayer_Basilisk"
map_data="border_size=1
usage=map

_off^_usr   , _off^_usr   , _off^_usr   , _off^_usr   , _off^_usr   , _off^_usr   , _off^_usr   ,        char *

加入:[join]id="1"observe="no"[/join]
<要加入的是ancientcc>
第二个消息:
[scenario_diff]
        [change_child]
                index="1"
                [side]
                        [insert]
                                current_player="ancientcc"
                                name="ancientcc"
                                player_id="ancientcc2"
                                save_id="ancientcc2"
                                user_description="ancientcc"
                        [/insert]
                        [delete]
                                id="x"
                        [/delete]
                [/side]
        [/change_child]
[/scenario_diff]
第三个消息
[change_faction]
        faction="0"
        gender="null"
        leader="random"
        name="ancientcc"
[/change_faction]

观察:[join]id="3"observe="yes"[/join]
<要加入的是ancientcc1>
回复

使用道具 举报

149

主题

331

帖子

2445

积分

版主

Rank: 7Rank: 7Rank: 7

积分
2445
沙发
 楼主| 发表于 2020-9-5 18:44:30 | 只看该作者

网络数据的压缩和解压缩

玩家发来命令,服务器转发向玩家命令,服务器产生事件,都是以压缩过形式在网络上流通。document封装一条命令/事件,内部操作支持了解缩和解压缩。注:这个一条是相对的,它可能是数条命令合成的一条命令,像send_history后形成的document。

要知道压缩和解压缩大概是怎么个过程首先就要了解document对象几个成员,它大概存储了什么内容。
  1. @compressed_buf:已压缩过数据。这往往是直接从网络上收到的数据。这个构造函数作就是根据网络上收到数据恢复出命令。
  2. document::document(string_span compressed_buf) :
  3.         compressed_buf_(compressed_buf),
  4.         output_(NULL),
  5.         buffers_(),
  6.         root_(NULL),
  7.         prev_(NULL),
  8.         next_(NULL)
  9. {
  10.         string_span uncompressed_buf;
  11.         // uncompress_buffer执行解压缩,解压缩后的数据放在从堆中分配出的一块内存
  12.         buffers_.push_back(uncompress_buffer(compressed_buf, &uncompressed_buf));
  13.         output_ = uncompressed_buf.begin();
  14.         const char* cbuf = output_;
  15.         try {
  16.                 root_ = new node(*this, NULL, &cbuf);
  17.         } catch(...) {
  18.                 delete [] buffers_.front();
  19.                 buffers_.clear();
  20.                 throw;
  21.         }

  22.         attach_list();
  23. }
  24. 至此大概可以总结下各个成员意义
  25. compressed_buf_:压缩过数据。
  26. buffers_:数据存储缓冲。它是一个vector,它的[0]存储的是未压缩过数据,[1]存储的是压缩过数据。注意下这两个数据都被从堆中分配,析构时要delete。
  27. output_:未压缩过数据。
  28. root_:<尚未理解>
复制代码
程序往往要遍历历史命令,这个遍历是通过把命令组织在一个链表,attach_list()作用就这是把这个命令放入链表。下图是使用的链表结构


send_history会遍历所有历史命令(但它不是通过链表),并在遍历时把所有命令合成一条命令,形成一个新的document
  1. 功能:把历史记录发向sock指定玩家。
  2. 注:在发送过程中,它会把原有记录合成一条记录,再写回历史容器
  3. void game::send_history(const network::connection sock) const
  4. {
  5.         if(history_.empty()) {
  6.                 return;
  7.         }

  8.         //we make a new document based on converting to plain text and
  9.         //concatenating the buffers.
  10.         //TODO: Work out how to concentate buffers without decompressing.
  11.         std::string buf;
  12.         for(std::vector<simple_wml::document*>::iterator i = history_.begin();
  13.             i != history_.end(); ++i) {
  14.                 // (*i)->output()返回是未压缩过数据
  15.                 buf += (*i)->output();
  16.                 delete *i;
  17.         }

  18.         try {
  19.                 simple_wml::document* doc = new simple_wml::document(buf.c_str(), simple_wml::INIT_STATIC);
  20.                 const simple_wml::string_span& data = doc->output_compressed();
  21.                 // 压缩
  22.                 doc->compress();
  23.                 network::send_raw_data(data.begin(), data.size(), sock,"game_history");
  24.                 history_.clear();
  25.                 history_.push_back(doc);
  26.         } catch (simple_wml::error& e) {
  27.                 WRN_CONFIG << __func__ << ": simple_wml error: " << e.message << std::endl;
  28.         }

  29. }
复制代码
回复 支持 反对

使用道具 举报

149

主题

331

帖子

2445

积分

版主

Rank: 7Rank: 7Rank: 7

积分
2445
板凳
 楼主| 发表于 2020-9-5 18:44:50 | 只看该作者
A:如何让0.1.6的客户端登陆进1.9.x的服务器?
Q:修改multiplayer.cpp中的open_connection(...),
  1. if(data.child("version")) {
  2.         config cfg;
  3.         config res;
  4.         cfg["version"] = game_config::version;
  5.         res.add_child("version", cfg);
  6.         network::send_data(res, 0, true);
  7. }
  8. cfg["version"] = game_config::version改为cfg["version"] = "0.1.5";
复制代码
A:登陆后,如何让0.1.6的客户端使用1.9.x的服务器?
Q:使用后要做到:
1、kingdom客户端不能“加入”、“观察”wesnoth创建游戏。
2、wesnoth客户端不能“加入”、“观察”kingdom创建游戏。
实现方法:
创建游戏时会发送[create_game]块,[create_game]中除了name字段可以有password。让kingdom创建游戏时使用一个固定密码(会使用checksum),客户端要加入需要这个密码。kingdom客户端会自动给出这个密码,wesnoth客户端则要求这个密码,但不知道这个密码无法“加入”、“观察”这个游戏。
改了era,让wesnoth客户端都认为是“未知时代”,以灰掉“加入”、“观察”按钮。



A:创建的游戏中含有较验码,避免客户端配置文件不一致的玩同一个剧本?
Q:
回复 支持 反对

使用道具 举报

149

主题

331

帖子

2445

积分

版主

Rank: 7Rank: 7Rank: 7

积分
2445
地板
 楼主| 发表于 2020-9-5 18:45:18 | 只看该作者

对韦诺之战服务器代码做的修改

服务器尽量会做到和韦诺之战服务器通用。能不改的尽量不改。

server::read_config()


当中要读服务器配置,这个配置往往被放在My Documents目录下,而在Windows下这个目录往往带中文,这时需要能解析中文目录名的读文件函数。
  1. scoped_istream stream = preprocess_file(config_file_);
  2. 改为
  3. scoped_istream stream = istream_file(config_file_, true);
复制代码
对于“建立联网游戏”,它是启动游戏时自动启动服务器,这时要读取的配置文件往往是放在My Documents目录下。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|丽谷软件|libsdl.cn

GMT+8, 2025-5-1 22:39 , Processed in 0.056466 second(s), 23 queries .

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表