yunfan 发表于 2005-7-1 19:00:28

有关libeva的使用说明 - 登录和登出操作

有关libeva的使用说明 - 登录和登出操作

首先,需要简单说一下腾讯QQ2005beta1的登录过程。

第一步。向服务器索要登录令牌, 对应的libeva的封装类为RequestLoginTokenPacket
第二步。得到登录令牌后, 则尝试登录一个腾讯服务器。 登录包的对应封装为 LoginPacket
第三步。如果服务器返回的是, 登录回应包的封装为 LoginReplyPacket
   3。1 QQ_LOGIN_REPLY_OK(0x00): 则说明登录成功
   3。2 QQ_LOGIN_REPLY_REDIRECT(0x01):说明服务器要求你更改新的服务器重新登录
   3。3 QQ_LOGIN_REPLY_PWD_ERROR(0x05):你的密码错误
   3。4 其他未知码: 意义不大了,其实我们只要上面三种情况就够了

   
现在,给出一个大概的编码逻辑,这里还是假定网络部分已经实现

这里假定一个方法叫做send(OutPacket *p),是发送数据包的。内容大体如下

void send(OutPacket *p){
    char *data = new char[MAX_PACKET_SIZE];
    int len = MAX_PACKET_SIZE;
   
    p.fill(data, &len);
   
    doSend(data, len); // 这里换成你发送数据的方法
   
    delete []data;
    delete p;// 注意如果p在之外还要用,就不要删了
}

在用户输入用户名和密码以后,我们需要首先设置libeva中Packet的QQ号,
和密码密钥(password key,就是对密码做2次md5后的字串, 细节可以参考“libeva使用说明-发送和接收”文档)
假如用户的 QQ号为12345, 密码为11111, 那么密码密钥就是d545c63da029385e7f46806156f8f51d,
我们假设密码密钥在一个char型的数组md5Pwd中,数组长度为16(注意密码密钥长度总是16)。

Packet::setQQ(12345); // 设置QQ号
Packet::setPasswordKey(md5Pwd); // 设置密码密钥
Packet::setUDP(true); // 这里设置是UDP登录。 参数为false就是TCP登录


完成了这些准备工作,我们就可以请求登录令牌了

RequestLoginTokenPacket *packet = new RequestLoginTokenPacket();
send(packet);


这里说明一下,有关接收数据和判断数据的类型,在“libeva使用说明-发送和接收”
中已经说明,就不再重复了。

这里假定分析登录令牌的回复方法如下

void processRequestLoginTokenReply(const InPacket *in)
{
        RequestLoginTokenReplyPacket *packet = new RequestLoginTokenReplyPacket();
        packet->setInPacket(in);
        packet->parse(); // 解析一下就可以了, 这个类会自动设置好loginToken
        delete packet;   // 释放点内存,这是个好习惯
       
        doLogin();// OK, 有了登录令牌,我们就可以登录了。
}


void doLogin()
{
    send(new LoginPacket(QQ_LOGIN_MODE_NORMAL));// 这就足够了, 够简单吧, 要是隐身登录,
                                                // 参数换成QQ_LOGIN_MODE_INVISIBLE 就OK了
}


现在我们来看看登录回应包的处理,

void processLoginReply(const InPacket *in)
{
      LoginReplyPacket *packet = new LoginReplyPacket();
      packet->setInPacket(in);
        if(!packet->parse()) {         // 我也不清楚是什么原因,有时候会出现解析失败,也许是网络的原因                               
                printf("parse error\n");// 但是大家放心, 总会正确的, 多检查一下总是好的,^_^
                return;
        }
        switch(packet->getReplyCode())
        {
        case QQ_LOGIN_REPLY_OK:
                // 到这里的话,那就是登录成功, 恭喜你!
                break;
        case QQ_LOGIN_REPLY_REDIRECT:
                // 如果到这里,说明服务器要求你转到其他服务器登录
                // 登录服务器的IP通过 packet->getRedirectedIP() 来得到,
                //             这个IP是个以本地字节序排列在一个int里(4字节)
                // 服务器的端口通过 packet->getRedirectedPort() 来得到,
                //             这个就是一个short型, 16字节
                break;
        case QQ_LOGIN_REPLY_PWD_ERROR:
                // 如果到这里则,说明你密码错误,而且服务器会返回一个“密码错误”之类
                // 的字符串, 你可以printf出来, 注意所以服务器的字符串编码,如果没有
                // 特殊说明,都是GB编码, GBK, GB18030 都可以
                printf("password error:%s\n",packet->getReplyMessage().c_str());
                break;
      default:
                // 我还没有见过到这里的, 你要是到了这里,还请告诉我, ^_^
                printf("unknown reply code\n");
        }
}


登录上了不是就完事了, 大概没隔1分钟,还是要向腾讯汇报一下,你还“活着”,否则,
腾讯服务器就不理你了,呵呵

   send(new KeepAlivePacket()); // 这样就可以了, easy?


对于上面的保持在线的回应包,没有多大用处, 里面就是目前腾讯服务器在线总人数,什么的。

void processKeepAliveReply( const InPacket * in )
{
        KeepAliveReplyPacket *packet = new KeepAliveReplyPacket();
        packet->setInPacket(in);
        packet->parse(); // 以上三步都是固定套路, 也许,我以后把这个写到一个方法里
        numOnlineUsers = packet->numOnlineUsers(); // 通过这个方法就可以得到当前在线总人数了
}


最后再说一下登出操作, 最简单就是这个了, 登出操作时,腾讯服务器是不会
回复的,只要扔4个一样的登出包给服务器就搞定了

        for(int i=0; i<4; i++)
                send(new LogoutPacket());

      // 现在已经登出腾讯服务器了,我们需要清理整个登录和会话
      // 过程中用到的所有的Key
      Packet::clearAllKeys();



ok, 总算说差不多了,现在大家,可以自己写一个简单地客户端了吧,呵呵
大家好运。^_^

最后:lol:再补充一下, 大家需要用eva 0.3.0 pre版中的 libeva 才行, 否则,
不灵的,呵呵, 就是登录的时候直接登就可以了,不需要什么登录令牌。

eva 0.3.0 pre 在这里去找把
http://www.magiclinux.org/people/yunfan

Anomymous 发表于 2005-7-1 22:39:20

for(int i=0; i<4; i++)
      send(new LogoutPacket());

如果没有扔出登出包结果会怎么样

不是每一分钟要向服务器报告吗?
那关闭程序是不递交登出包也一样啊

yunfan 发表于 2005-7-1 23:14:47

for(int i=0; i<4; i++)
      send(new LogoutPacket());

如果没有扔出登出包结果会怎么样

不是每一分钟要向服务器报告吗?
那关闭程序是不递交登出包也一样啊

这个随便你,你也可以那么做。 就是你的好友不能马上知道你走人了而已。

yunfan 发表于 2005-7-3 12:51:22

对不起大家,刚才查了一下Eva源代码,登录回复中,如果是重定向的话, 那个方法取到的IP是以本地字节序排列的一个INT,而不是网络字节序。

Anomymous 发表于 2005-7-22 10:20:11

libeva使用说明-发送和接收”文档中没有MD5的介绍呀

Anomymous 发表于 2005-7-22 10:33:12

我在C++BUlider中用doMd5Md5,运行时出现: Unresolved external '_md5_append' referenced from F:\QQTEST\LIBEVA\EVAUTIL.OBJ, Unresolved external '_md5_finish' referenced from F:\QQTEST\LIBEVA\EVAUTIL.OBJ,                                                                Unresolved external '_md5_init' referenced from F:\QQTEST\LIBEVA\EVAUTIL.OBJ?
是什么原因呀??

Miliardo 发表于 2005-8-3 10:11:45

用Windows我也没说你什么……
你怎么用BCB啊……那些似乎是OpenSSL的函数……

涩兔子 发表于 2006-3-28 20:55:46


if (libeva is written by C programming language = true) then
      Akomedia Co. Ltd. will port it into Akomedia IPTV Middleware;
else
      Yunfan rewrite it in C programming language;

if (Akomedia Co. Ltd. will port libeva into Akomedia IPTV Middleware = true) then {
      Akomedia's DITVS supports MSN and QQ both;
      Akomedia Co. Ltd. will type "Show me the money" inStarCraft;
}

Please visit www.akomedia.com for more information *^_^*

Cheers,
Jackey Yang

baif 发表于 2006-3-28 22:18:07

show me the money...

yunfan 发表于 2006-3-29 10:25:53

Jacket 哪里说的那段psudo code, 兔子, 你们机顶盒用的库都是gtk的吧。
页: [1]
查看完整版本: 有关libeva的使用说明 - 登录和登出操作