QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 5215|回复: 7

有关libeva的使用说明-发送和接收消息

[复制链接]
发表于 2005-6-26 10:49:50 | 显示全部楼层 |阅读模式
为了大家可以更容易的利用libeva来实现自己的QQ客户端,
我把发送消息和接收消息的部分简单的说一下,给一点例子。

这里假设网络部分已经处理好了。

先说一下发送的流程:
客户端发一条消息, 服务器回复,表示收到你发的消息。

接收流程:
服务器发给你一条消息, 你如果可以正确解析,则发给服务器一个返回,表示你正确收到了。


发消息,就没什么说的了,大致代码如下
[code:1]
SendTextIMPacket *IMPacket = new SendTextIMPacket();
IMPacket->setReceiver(123456); // 对方的QQ号,123456
IMPacket->setAutoReply(false); // 是正常聊天消息,不是自动回复
IMPacket->setMessage("你好");  // 消息内容, 是个std::string 类型,这个字符串一定要是GB编码的,GBK, GB18030都可以。

//这里是发送前处理
int len = 65535;
char *buf = new char[len];
IMPacket->fill(buf, &len);   // 填充最终发送内容
//然后发送 buf, 长度就是len。
[/code:1]

收消息是要注意, 每次收到消息,要发上给服务器发一个包,包内容是收到的包的前16个字节
这是告诉服务器,“我”收到你的消息了,否则,服务器会重复发多个。
[code:1]
//packet是你收到的那个来自服务器的消息,通过getReplyKey这个方法
//可以得到回复用的前16个字节, 然后设置要回复的包序号,然后发送
ReceiveIMReplyPacket *packetReply = new ReceiveIMReplyPacket(packet->getReplyKey());
packetReply->setSequence(packet->getSequence());

//这里是发送前处理
int len = 65535;
char *buf = new char[len];
IMPacket->fill(buf, &len);
//然后发送 buf, 长度就是len。
[/code:1]

要注意的是,每次发送给服务器一条消息,服务器总回给一个返回,表示
成功收到还是不成功,如果收不到,需要客户端重新再发一次,确保服务器正确
地收到。下面就会说到。


下面是收消息的处理
[code:1]
// 收到字节后首先判断是什么命令
// rawData 就是收到的字节,len是收到的字节数目
InPacket *in = new InPacket((unsigned char *)rawData, len);

//然后根据命令,来执行不同的部分,来解析数据

if (in->getCommand() == QQ_CMD_RECV_IM ){ // 如果是有消息到来
        ReceiveIMPacket *packet = new ReceiveIMPacket();
        packet->setInPacket(in);
        if(packet->parse()){   // 初步解析消息头,如果成功, 发一个确认收到的消息给服务器
            ReceiveIMReplyPacket *packetReply = new ReceiveIMReplyPacket(packet->getReplyKey());
            packetReply->setSequence(packet->getSequence());
            connecter->append(packetReply);  // 这里换成你自己的发送代码
        }else
            return;  // 否则忽略就可以了。
            
        switch(packet->getIMType()){  // 判断具体聊天消息类型
        case QQ_RECV_IM_TO_BUDDY:     // 来自好友的消息
        case QQ_RECV_IM_TO_UNKNOWN:{  // 来自陌生人的消息, 好友和陌生人的消息格式是一直的,都是普通文本聊天消息
                NormalIMBase *base = new NormalIMBase(packet->getBodyData(), packet->getBodyLength());
                base->parseData();  
                switch(base->getNormalIMType()) // 判断是普通聊天消息,也可能是文件传输的一些请求
                {
                case QQ_IM_NORMAL_TEXT:{ // 如果是普通聊天消息
                        ReceivedNormalIM * received = new ReceivedNormalIM();
                        received->setNormalIMBase(base);
                        received->parseData();
                       
                        // 现在消息全在received里了
                        // 你可以通过ReceivedNormalIM 类的方法来取消息内容,字体信息 等等.
                        delete received;
                        }
                        break;
                default: // 否则,其它类型,不管它
                        printf("Got a non-text msg, can't process it, ignore it\n");
                }
                delete base;
                }
                break;
        default:
                printf("message code: 0x%4x -- sender:%d  -- Unknown\n",packet->getSender(), packet->getIMType());
        }
        delete packet;
}
[/code:1]

注意可能libeva部分的代码有改动, 就是parse(), 以前好像是void型,
现在改成bool型了, 如果是void型, 不用判断, 直接发确认给服务器好了。

这里我只是简单说了一下,发送和接收, 尤其是接收,在QQ中会收到很多不同的聊天消息,
像群,认证什么的。 具体的参考api目录下的 evapacketmanager.cpp的文件内容吧。
发表于 2005-6-26 20:10:56 | 显示全部楼层
建议继续封装.....在封装得简单一点
回复

使用道具 举报

发表于 2005-6-28 09:22:29 | 显示全部楼层
放假以后 我也要用用libeva
回复

使用道具 举报

发表于 2006-1-6 03:06:49 | 显示全部楼层
弱弱的问一下libeva本身如何编译呢?
它的依赖如何,如果没有QT开发环境可以吗?
它和lumaqq的lib有一些相似点,就我个人观点啦,没有仔细看。
我们以前的开发多半是照翻luma的java到C++,不知道,转移到libeva的可能性!
请指教,谢谢,我想避免没意义的重复开发,把更多的时间来做界面上的东西。
PS:我所说的就是cyclone,初衷是要基于gtk的,最后搞成gtkmm的,因为许多人没有KDE环境,造成了我们无法使用eva的情况。谢谢。我们懂协议的开发者,失踪中!  
回复

使用道具 举报

发表于 2006-1-6 08:53:53 | 显示全部楼层
如果在调用libeva时需要改动的话,不利于打包。向这种情况,在debian下肯定要将libeva做成一个包的。
回复

使用道具 举报

 楼主| 发表于 2006-1-6 15:00:28 | 显示全部楼层
[quote:ad79f191fe="swjbook"]弱弱的问一下libeva本身如何编译呢?
它的依赖如何,如果没有QT开发环境可以吗?
它和lumaqq的lib有一些相似点,就我个人观点啦,没有仔细看。
我们以前的开发多半是照翻luma的java到C++,不知道,转移到libeva的可能性!
请指教,谢谢,我想避免没意义的重复开发,把更多的时间来做界面上的东西。
PS:我所说的就是cyclone,初衷是要基于gtk的,最后搞成gtkmm的,因为许多人没有KDE环境,造成了我们无法使用eva的情况。谢谢。我们懂协议的开发者,失踪中!  [/quote]

刚看到这个贴, 不好意思。

libeva 目前是放在eva中编译的。 假如说把libeva放到 cyclone中,
我猜测是可能的。  libeva 中的东西不需要Qt或者KDE的任何东西,
只需要g++, 因为这部分仅仅封装了QQ的协议而已, 完成解密,
解析内容, 封装内容, 加密 的功能, 仅此而已。

你可以改动Makefile.am 把这部分做成so, 最简单的就是直接复制这个
目录到你的项目中, 然后改动相应的Makefile.am 加入libeva这个目录,
然后,就可以直接用了。

另外, 其实大家可以一起来分析协议, 完善libeva, 然后实现不同的
图形前端, 满足不同的需要:)
回复

使用道具 举报

发表于 2006-1-7 09:50:28 | 显示全部楼层
呵呵,感谢云帆的回复。不管是否直接采用libeva,从这里借鉴是肯定要得啦。大家的目的都是一样的。就是希望给linux用户或者玩家提供更多更好的开源软件。
协议的解析的话,很惭愧,现在还帮不上忙,我会好好研读,争取尽快赶上来,大家一起来完善它。
祝eva 越弄越好啊。
回复

使用道具 举报

 楼主| 发表于 2006-1-7 10:34:44 | 显示全部楼层
刚想起来, 由于开始设计libeva这部分的时候, 没有考虑到多帐号的问题,
导致了libeva存在了一些先天性的缺点。 直接在cyclone中使用是不可能的,
libeva的包封装基类中使用了大量的static变量, 这个是为了简化api, 尽量
不让用户涉及这些麻烦的key的直接操作的, 但是反过来, 这个就导致了
目前无法使用多用户同时登录, 如果进行修改, 又牵扯api的更改, 很多上层
代码也要修改。 我太懒, 不想找太多麻烦, 就没有修正:)。 但是, 里面
大部分代码是可以直接复制到cyclone中的。

还有, 对于libeva本身的构架, 随着对腾讯协议了解的增加, 发现原来的
设计存在着一些不好的地方, 比如, 对好友列表, 群列表 等等的 设计上,
以及包基类的设计上,不能很好的统一全部包的形态和行为(这包括了其它类型
的包, 比如文件传输, 自定义头像下载等等, 其实就是抽象度和概括度不够高)。
所以, 希望你们在开发的过程中, 可以避免这些问题。

当初设计libeva的思想是受cjacker的提示, 遵循luma的包封装的基本思想,
基于当时对QQ协议的理解, 匆匆实现的, 目的就是设计一个可以重复利用
的协议封装库。目前看来还有很多不足, 但还是一个可以使用的库。

cyclone的代码我也匆匆浏览过, c++功底比我要深, 还希望,我们大家可以
集中力量, 来实现一个通用的QQ协议封装类。 Qt4 即将全面登场了,估计今年
年底之前, kde也将全部升级到qt4 上, 那么eva 的上层代码很多都要重新设计
和更改, 如果可能, libeva 也重新设计和实现吧(如果有更多人加入的话 :-) )。
回复

使用道具 举报

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

本版积分规则

GMT+8, 2024-11-22 03:18 , Processed in 0.085902 second(s), 15 queries .

© 2021 Powered by Discuz! X3.5.

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