网络验证开发思路火花

本文采用C/S架构。

用户登陆验证

这个比较容易,select用户table的user、pass字段,若查询失败则登陆失败,反之,则登陆成功。

产品是否到期

伪代码: return (到期时间的时间戳 >= 现在时间的时间戳);
返回true则产品已经过期,false则还没有过期。

Session

在用户table里建一个 session id 字段
用户登陆成功后,S端生成(要替换掉旧的 session id)并返回一个 session id(必须独一无二)。
S端需要有一个验证 session id 的函数。

C端登陆后

C端登陆成功后让外挂DLL知道刚才从S端过来的 session id,然后访问S端的验证 session id 函数,检查对不对。

防多个用户同时使用(非实时)

C端每隔3分钟访问一下S端的 session id 验证函数,检查是否OK。(意思就是,新用户登陆之后,旧的 session id 就会废掉)
若某个 session id 超过10分钟没有访问过验证函数,则删掉该 session id。

std::map 的一个很机智用法

前提是你的编译器必须支持 C++11,否则编译不通过。

#include <iostream>
#include <typeindex>
#include <typeinfo>
#include <string>
#include <map>

class foo
{
public:
    foo()
    {}

    template <typename T>
    void test(T type, std::string msg)
    {
        // 将对应type的msg修改
        map_[typeid(type)] = &msg;
        // 输出对应值
        std::cout << *map_.at(typeid(type)) << std::endl;
    }
private:
    std::map<std::type_index, std::string*> map_;

};

int main()
{
    foo f;
    f.test(2333, "Hello"); // int
    f.test(2333.3, "World"); // double

}

分析

typeid 返回 std::type_index。
foo::test有两个参数,一个是模板参数,一个是 std::string。
map_[typeid(type)] = &msg; 的意思是,设置 map_[typeid(type)] 的值。
这个时候,f.test(2333, "Hello"); 会处理到 int,就会设置 map_[typeid(int)] 的值 (注意int)。
以此类推。这个一般应用在消息处理上(夏幻菊苣说的),或者这个上面。

换行符

为了在写程序的时候不用上网查,窝特地写了一个blog来记录一下,需要的时候看就可以了。

在 Unix-like 的所有系统,都是以 "\n" 作为换行符。
注: 在比较旧的 Mac 系统上,是以 "\r" 作为换行符。
在 Windows 上都是以 "\r\n" 作为换行符。
就酱

在 GitHub 上使用 GnuPG

效果大概是这样:
screenshot

首先,创建一个 gpg key,这个比较简单,就略过了。
然后 key 的 id 是 2F6A12EF49B4426012129ED0CA3435EDDAEE3483,设置 git 签名公钥为 2F6A12EF49B4426012129ED0CA3435EDDAEE3483

$ git config --global user.signingkey 2F6A12EF49B4426012129ED0CA3435EDDAEE3483

导出 key 的公钥,并上传到GitHub服务器:

$ gpg --armor --export 2F6A12EF49B4426012129ED0CA3435EDDAEE3483
-----BEGIN PGP PUBLIC KEY BLOCK-----

mQENBFkYPJoBCAC9cHHySDMhfWoV6DpsLT6GQOV1F6T/5qqBxWWJ2Jdy1F1HRY7w
28tFHHdAA4qNC8aqQB33zWKWmm92Nr+aM7rvvY5Jza2Q3xANXrnZHi2ztSkPv0/j
rqnXH/E+5uLbQMMuJjwFWni/spgYbpBHBiFchh5m7nNZY4SqrSCPcFBhWbC4y6zC
vsQpnojzbzeY6ald6OsVw0dYC46DXzHqlqDhek0xVaoeYJU894n8vGkNShEFienI
7nozLZck1rjhSxBuKSELu3ZvOmMxYiu9PdrzxVvv3ZX0Tzdk/cM78rGtq0PXqrbQ
ICUcT9l3OVq9zbHS9dautHSo320wmF8R82BzABEBAAG0G0ppbmdKaW5nSGFjayA8
aUBrZXJuZWwubW9lPokBVAQTAQgAPhYhBC9qEu9JtEJgEhKe0Mo0Ne3a7jSDBQJZ
GDyaAhsDBQkDwmcABQsJCAcCBhUICQoLAgQWAgMBAh4BAheAAAoJEMo0Ne3a7jSD
U24H/A7M6UiNlbkyShFVXVl5eo2cj3KWbABVjaKEWAPlX9H6Nuzt4kv7qP4DWLd5
p20L/zap0NDpSvmTXUlEmzPy8P9lp9rlywNtK9DHp8vONPxEf1KXP+P3HWEAa8eU
KpGAp/G9y9kHh0+Yw4nqfQB4VsgLMq1a9sAq02g0oxn44Q4PLDa3BdDJAhKsC5Jt
gsrr07s8+3W7ahhbXxCQ0ROFgv6Z0erijmpmYy+d7hdvl22CzbGoY+DEpVFRpPXy
3pF+n01GE2CJrSnu4RFLp4KEtozlBqZ3CcoE0qruhm6AwAqVuOWdDdncQxykeE8q
5G7P1gKtslotF7Bz9YVH7EGNjCO5AQ0EWRg8mgEIAMf4ulkoT1wXp1kdTPSOsFzU
fEWmWIfqbtDXu8aE7u0GrqhMo6I9oopR6k9wGOmV6U0ttevS6xDUb7OBTkUW4PNy
2X6UQ4LtKZFwvCw3qnMCDQCI9R5Wjm5xzc9lzLHjV9tRX9tNA2G/YETYoNp2HMI0
wVif5fRwdTXrHF9EoKRhUgFdbJxdqEBMR0feyv9PZ2pGpYWsOgF2k5en6lmOuQCJ
rWnbFyzrp6cWIl880yrD+J9EedXivINcOb10HB3Kr/+q2qQ+h2BYgaUgVenNEbQR
F9cMylWZhdV3ZM+uoOQIJku/Vsdy+wkUK5kLONJvH1ZtDyTmHE0l7DYcJOaG4rkA
EQEAAYkBPAQYAQgAJhYhBC9qEu9JtEJgEhKe0Mo0Ne3a7jSDBQJZGDyaAhsMBQkD
wmcAAAoJEMo0Ne3a7jSDhswH/3E1UWS9Y31GxlJCeUXbJk819QydAkHTm3mUttYB
N8l1NdtbZESQgt/42ZknuZlZRPpsKOkP52nqdwOaoA+HKoc/VnlYVQqAEVEZkSZg
9wP6olRu0h4O181AMI9PTvoyIW830lj/urpW1vljNl1hNI/2raC4IG2M/v+/+3qb
BWuYEvCguzbOci4mkGpacGFeM8DywCr5ZZB1zSXTmUyOutl2BF9eebRjrEXrhy0+
rQ8Fo4X45VcC9bXvtQjevzWkEMhaviA93eXMvO1muanFy9ApOhzO74y688Rax5Jv
WlvGslgg4kO3byO5SvRG1y1FCjDbHwy1hO4wTX+fsDQ5q+w=
=zXH3
-----END PGP PUBLIC KEY BLOCK-----

添加 key 公钥到 GitHub 之后,在你的 GitHub repo 里提交一个 commit:

$ git commit -m "test" -S

发现多了一个 -S 参数,这个参数是 Signature 的缩写,意思大家应该懂得。
然后输入 git log --show-signature 可以看到有一个类似这样的文本: gpg: Good signature from "JingJingHack <i@kernel.moe>" [ultimate]
每次都需要加一个 -S 会发现很繁琐,可以设置git,让它自动签名。

$ git config commit.gpgsign true # 只对该项目有效
$ git config --global commit.gpgsign true # 全局(所有项目都使用GPG签名)

字节序笔记

先来简单的理解小端序和大端序。

大端序

大端序是字节序的一种,也是比较常用的一种。
Java 语言就是使用大端序来存储。
假设你有一个 int 型的变量,它的值为 23333,对应的十六进制是 0x5B25
在大端序中内存是这样存储的:

0x001 5B
0x002 25

数据的增长方向在右边,

小端序

再拿 23333 和 int 来做示例,在小端序中内存是这样存储的:

0x001 25
0x002 5B

它跟大端序是反向的,阅读顺序是从左到右,数据的增长方向也是右。

mc protocol

因为 mc 使用的是 Java,所以使用的是大端序,而我的环境是使用小端序的(x86架构cpu c++语言)。
看起来只要把小端序转成大端序就可以啦,至于字节序的转换嘛,boost 爸爸已经实现了相关库:

#include <boost/endian/conversion.hpp>
void test()
{
   int v1;
   int v2 = boost::endian::native_to_big<int>(v1); // 把本地使用的字节序转成大端序
}