感谢支持
我们一直在努力

Linux下仿QQ–eva0.4.1源码研究

争取一天看一个文件,随便找一个好看的看起eva/src/api/evaipseek

#ifndef EVAIPSEEKER_H
#define EVAIPSEEKER_H
#include <string>
#include <fstream>
//一看头文件,只有file操作,看来不是socket相关
class EvaIPSeeker
{
public:
  EvaIPSeeker();
  EvaIPSeeker(std::string absPath);
  ~EvaIPSeeker();
  const std::string getIPLocation(const std::string ip);
  const std::string getIPLocation(const unsigned int ip);
  const bool isQQWryExisted();
                                             
private:
  unsigned int searchIP(const unsigned int ip);
  unsigned int readIP(unsigned int offset);
  unsigned int getMiddleOffset(const unsigned int begin, const unsigned int end);
  int compareIP(const unsigned int ip1, const unsigned int ip2);
  std::string getIPRecord(const unsigned int offset);
  std::string readString(const unsigned int offset);
  std::string readArea(const unsigned int offset);
  bool getIndexOffset(std::fstream& inputfile);
                                             
private:
  std::fstream ipFile;    //file i/o stream
  std::string fileName;    //the data file path
  int firstIndexOffset;    //the first index offset of the index area
  int lastIndexOffset;    //the last index offset of the index area
  char byte4[4];          //tmp char array
  char byte3[3];          //tmp char array
};
#endif

 

/***************************************************************************
 *  Copyright (C) 2005 by casper                                          *
 *  tlmcasper@163.com                                                    *
 *                                                                        *
 *  This program is free software; you can redistribute it and/or modify  *
 *  it under the terms of the GNU General Public License as published by  *
 *  the Free Software Foundation; either version 2 of the License, or    *
 *  (at your option) any later version.                                  *
 *                                                                        *
 *  This program is distributed in the hope that it will be useful,      *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
 *  GNU General Public License for more details.                          *
 *                                                                        *
 *  You should have received a copy of the GNU General Public License    *
 *  along with this program; if not, write to the                        *
 *  Free Software Foundation, Inc.,                                      *
 *  59 Temple Place – Suite 330, Boston, MA  02111-1307, USA.            *
 ***************************************************************************/
#include <iostream>
#include <string>
#include <fstream>
#include “evaipseeker.h”
#include “evaipaddress.h”//这里还依赖一个文件,看来得看看这个
#define STRING_LEN        80
#define IP_RECORD_LENGTH  7
#define REDIRECT_MODE_1  0x01
#define REDIRECT_MODE_2  0x02
#define DATAFILENAME      “QQWry.dat” //qq直接用文件,都不用sql
#define READINT3(X) (( X[0] & 0xFF )|(( X[1] & 0xFF)<< 8 )|(( X[2] & 0xFF )<< 16 ))  //用移位操作的都是高手,是否?
#define READINT4(X) (( X[0] & 0xFF )|(( X[1] & 0xFF)<< 8 )|(( X[2] & 0xFF )<< 16 )|(( X[3] & 0xFF ) << 24 ))
using namespace std;
//get the path of IP data file which is in the working directory,store in @fileName
//param:null
//return:null
EvaIPSeeker::EvaIPSeeker()
{
  fileName = DATAFILENAME;
}
//get the absolute path of IP data file,store it in @fileName;
//param: string absPath
//return: null
EvaIPSeeker::EvaIPSeeker(string absPath)
{
  fileName = absPath + “/” + DATAFILENAME;
}
//check the status of IP data file,close it if it opened.
//param: null
//return: null
EvaIPSeeker::~EvaIPSeeker()
{
  if(ipFile.is_open())
      ipFile.close();
}
//check if QQWry.dat exists
//param: null
//return: true or false
const bool EvaIPSeeker::isQQWryExisted()
{
  ipFile.open(fileName.c_str(), ios::in);
  if(!ipFile)
    return false;
  else
  {
    ipFile.close();
    return true;
  }
}
//search ip in the index area of IP data file,return the offset of IP record if found.
//param: unsigned int ip
//return: unsigned int offset
unsigned int EvaIPSeeker::searchIP(const unsigned int ip)
{
  unsigned int startIP;
  unsigned int endIP;
  unsigned int midIP,mOffset;
  int r;
  unsigned int i,j;
  startIP = readIP(firstIndexOffset);
  endIP = readIP(lastIndexOffset);
  r = compareIP(ip,startIP);
  if(r == 0)
      return firstIndexOffset;
  else if(r < 0)
      return 0;
  for(i = firstIndexOffset, j = lastIndexOffset; i < j;)
  {
    mOffset = getMiddleOffset(i, j);
    midIP = readIP(mOffset);
    r = compareIP(ip, midIP);
    if(r > 0)
      i = mOffset;
    else if(r < 0)
    {
      if(mOffset == j)
      {
        j -= IP_RECORD_LENGTH;
        mOffset = j;
      }
      else
        j = mOffset;
    }
    else
    {
      if(!ipFile.is_open())
          ipFile.open(fileName.c_str(), ios::in|ios::binary);
      ipFile.seekg(mOffset+4, ios::beg);
      ipFile.read(byte3, 3);
      ipFile.close();
      return READINT3(byte3);
    }
  }
  if(!ipFile.is_open())
      ipFile.open(fileName.c_str(), ios::in|ios::binary);
  ipFile.seekg(mOffset+4, ios::beg);
  ipFile.read(byte3, 3);
  midIP = readIP(READINT3(byte3));
  r = compareIP(ip, midIP);
  if(r <= 0) return READINT3(byte3);
  else return 0;
}
//read 4 bytes start from the offset,and change them to an IP address.
//param: unsigned int offset
//return: unsigned int IP
unsigned int EvaIPSeeker::readIP(unsigned int offset)
{
  unsigned int tmpIP;
  if(!ipFile.is_open())
      ipFile.open(fileName.c_str(), ios::in|ios::binary);
  ipFile.seekg(offset, ios::beg);
  ipFile.read(byte4,4);
  tmpIP = READINT4(byte4);
  ipFile.close();
  return tmpIP;
}
//compare two IP
//param: unsigned int ip1, unsigned int ip2
//return: int result
int EvaIPSeeker::compareIP(const unsigned int ip1, const unsigned int ip2)
{
  if( ip1 > ip2 ) return 1;
  else if ( ip1 < ip2 ) return -1;
  else  return 0;
}
//get the middle offset of two offsets.
//param: unsigned int begin, unsigned int end
//return: unsigned int theMiddleOffset
unsigned int EvaIPSeeker::getMiddleOffset(const unsigned int begin, const unsigned int end)
{
  int records = (end – begin) / IP_RECORD_LENGTH;
  records >>= 1;
  if(records == 0) records = 1;
  return begin + records * IP_RECORD_LENGTH;
}
//read a string start from the offset until meet a char ‘\0’
//param: unsigned int offset
//return: string str
string EvaIPSeeker::readString(const unsigned int offset)
{
  static char tmpstr[STRING_LEN];
  string str;
  ipFile.seekg(offset, ios::beg);
  ipFile.getline(tmpstr,STRING_LEN,’\0′);
  str = tmpstr;
  return str;
}
//get one IP record (country and area) of the offset
//param: unsigned int offset
//return: string location
string EvaIPSeeker::getIPRecord(const unsigned int offset)
{
  char flag;
  string country;
  string area;
  string location;
  unsigned int countryOffset;
  if(!ipFile.is_open())
      ipFile.open(fileName.c_str(), ios::in|ios::binary);
  ipFile.seekg(offset+4, ios::beg);//ignore the ip data
  ipFile.get(flag);
  if(flag == REDIRECT_MODE_1)
  {
    ipFile.read(byte3, 3);
    countryOffset = READINT3(byte3); //get the offset of country data
    ipFile.seekg(countryOffset);
    ipFile.get(flag); // check the flag again,maybe it’s an other redirectroy
    if(flag == REDIRECT_MODE_2)
    {
      ipFile.read(byte3, 3);
      country = readString(READINT3(byte3));
      ipFile.seekg(countryOffset+4);//if mode2,we need pass 4 bytes to reach the area data;
    }
    else
    {
      country = readString(countryOffset);
    }
    area = readArea(ipFile.tellg());
  }
  else if(flag == REDIRECT_MODE_2)
  {
    ipFile.read(byte3, 3);
    country = readString(READINT3(byte3));
    area = readArea(offset+8);
  }
  else
  {
    ipFile.putback(flag);//make the inside pointer back 1 character
    country = readString(ipFile.tellg());
    area = readArea(ipFile.tellg());
  }
  location = country + area;
  ipFile.close();
  return location;
}
//read the Area data start from the offset.
//param: unsigned int offset
//return: string areaData
string EvaIPSeeker::readArea(const unsigned int offset)
{
  char flag;
  unsigned int areaOffset;
                                       
  ipFile.seekg(offset, ios::beg);
  ipFile.get(flag);
  if(flag == REDIRECT_MODE_1 || flag == REDIRECT_MODE_2)
  {
    ipFile.read(byte3, 3);
    areaOffset = READINT3(byte3);
    if(areaOffset != 0)
      return readString(areaOffset);
    else
      return “Unknow Area”;//if the areaoffset is zero,it’s show there’s no data for the area
  }
  else
    return readString(offset);
}
//get the Index arrange of the Index area from infile
//param: fstream& infile
//return: true or false
bool EvaIPSeeker::getIndexOffset(fstream& infile)
{
  infile.seekg(ios::beg);
  infile.read(byte4, 4);
  firstIndexOffset = READINT4(byte4);
  infile.read(byte4, 4);
  lastIndexOffset = READINT4(byte4);
  if(( firstIndexOffset == -1 )||( lastIndexOffset == -1 ))
  {
    return false;
  }
  return true;
}
//main function, get the location of an IP address,if IP is not valid or the Data file missed then return IP address.
//param: unsigned int ip
//return: string location or string ip
const string EvaIPSeeker::getIPLocation(const unsigned int ip)
{
  EvaIPAddress addr(ip);
  if(!isQQWryExisted())
    return addr.toString();
  ipFile.open(fileName.c_str(), ios::in|ios::binary);
  if(!ipFile)
    return addr.toString();
  else
  {
    if(!getIndexOffset(ipFile))
    {
      ipFile.close();
      return addr.toString();
    }
    return getIPRecord(searchIP(addr.IP()));
  }
}
//main function, get the location of an IP address,if IP is not valid or the Data file missed then return IP address.
//param: string ip
//return: string location or string ip
const string EvaIPSeeker::getIPLocation(const string ip)
{
  EvaIPAddress addr(ip);
  if(!addr.isValid())
    return addr.toString();
  if(!isQQWryExisted())
    return addr.toString();
  ipFile.open(fileName.c_str(), ios::in|ios::binary);
  if(!ipFile)
    return addr.toString();
  else
  {
    if(!getIndexOffset(ipFile))
    {
      ipFile.close();
      return addr.toString();
    }
    return getIPRecord(searchIP(addr.IP()));
  }
}

更多详情见请继续阅读下一页的精彩内容: http://www.linuxidc.com/Linux/2013-10/92148p2.htm

相关阅读:

Ubuntu7.10下安装最新版EVA QQ来聊天 http://www.linuxidc.com/Linux/2007-11/9003.htm

CentOS下安装EVA QQ  http://www.linuxidc.com/Linux/2013-07/87051.htm

没看到具体的关键实现,只是一个文件检索。保存了ip,国家,地区信息。忽略之。

#ifndef EVAIPADDRESS_H
 #define EVAIPADDRESS_H
                       
 #include <inttypes.h>
 #include <string>
 /*
    this class is only for ipv4 addresses
    this class can be used as below:
                         
    EvaIPAddress addr(“255.255.255.255”); // or EvaIPAddress addr(0xffffffff) ;
    uint ip = addr.IP();
    std::string strIP = addr.toString();
 */
 class EvaIPAddress{
 public:
    EvaIPAddress() {};
    EvaIPAddress(const uint ip);
    EvaIPAddress(const std::string &strIP);
    EvaIPAddress(const EvaIPAddress &address);
                         
    void setAddress(const uint ip);
    void setAddress(const std::string &strIP);
    const bool isValid() const;
    const uint IP() const;
    const std::string toString();
    EvaIPAddress &operator= (const EvaIPAddress &rhs);
private:
    bool isValidIP;
    uint mIP;
    uint getIntIP(const std::string &strIP);
};
                       
#endif

看着头文件,也只是一个工具类。

/***************************************************************************
 *  Copyright (C) 2005 by yunfan                                          *
 *  yunfan_zg@163.com                                                    *
 *                                                                        *
 *  This program is free software; you can redistribute it and/or modify  *
 *  it under the terms of the GNU General Public License as published by  *
 *  the Free Software Foundation; either version 2 of the License, or    *
 *  (at your option) any later version.                                  *
 *                                                                        *
 *  This program is distributed in the hope that it will be useful,      *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
 *  GNU General Public License for more details.                          *
 *                                                                        *
 *  You should have received a copy of the GNU General Public License    *
 *  along with this program; if not, write to the                        *
 *  Free Software Foundation, Inc.,                                      *
 *  59 Temple Place – Suite 330, Boston, MA  02111-1307, USA.            *
 ***************************************************************************/
               
#include “evaipaddress.h”
#include <stdlib.h>
EvaIPAddress::EvaIPAddress(const uint ip)
    :isValidIP(false)
{
    mIP = ip;
    isValidIP = true;
}
EvaIPAddress::EvaIPAddress(const std::string &strIP)
    :isValidIP(false)
{
    mIP = getIntIP(strIP);
    if(mIP)
        isValidIP = true;
}
EvaIPAddress::EvaIPAddress(const EvaIPAddress &address)
    :isValidIP(false)
{
    mIP = address.IP();
    isValidIP = address.isValid();
}
void EvaIPAddress::setAddress(const uint ip)
{
    mIP = ip;
}
void EvaIPAddress::setAddress(const std::string &strIP)
{
    mIP = getIntIP(strIP);
}
const bool EvaIPAddress::isValid() const
{
    return isValidIP;
}
const uint EvaIPAddress::IP() const
{
    return mIP;
}
const std::string EvaIPAddress::toString()
{
    char strIP[16];
    memset(strIP, 0, 16);
    sprintf(strIP, “%d.%d.%d.%d”, (mIP&0xFF000000)>>24, (mIP&0x00FF0000)>>16, (mIP&0x0000FF00)>>8, (mIP&0x000000FF));
    return std::string(strIP);
}
EvaIPAddress &EvaIPAddress::operator= (const EvaIPAddress &rhs)
{
    mIP = rhs.IP();
    isValidIP = rhs.isValid();
    return *this;
}
uint EvaIPAddress::getIntIP(const std::string &strIP)
{
    int num = 0;
    for(uint i=0; i< strIP.length(); i++)
        if(strIP[i] == ‘.’) num++;
    // check if it consists of 4 parts
    if(num != 3){
        isValidIP = false;
        return 0;
    }
                 
    // get all 4 parts in
    unsigned char parts[4];
    int start = 0, end = 0;
    for(int i=0; i<4; i++){
        for(uint j= start; j<strIP.length(); j++){
            if(strIP[j] == ‘.’){
                end = j;
                break;
            }
            if(strIP[j] < ‘0’ || strIP[j] > ‘9’){
                isValidIP = false;
                return 0;
            }
        }
        //printf(“3 strIP:%s\n”,strIP.c_str());
        std::string tmp = strIP.substr(start, end – start);
        int tmpInt = atoi(tmp.c_str());
                     
        if(tmpInt< 0 || tmpInt > 255){
            isValidIP = false;
            return 0;
        }
        parts[i] = (unsigned char)tmpInt;
        start = end + 1;
    }
    // put all 4 parts into one uint
    return ((uint)parts[0])<<24 | ((uint)parts[1])<<16 | ((uint)parts[2])<<8 | parts[3];
}

不错,这个工具类,自己可以随时用到。 随时拿来主义。嘎嘎

刚看了2个文件,都很基础,没花时间,接着看。。。

#ifndef EVACONNECTER_H
#define EVACONNECTER_H
#include <qobject.h>
#include <qptrlist.h>//ptr-list,指着list,qt还有这list
#include <qhostaddress.h>
#include <qstring.h>
#include “evapacket.h” //看来又得多看2个文件
#include “evanetwork.h”
class QTimer; //o ,要是定时判断,connect–timeout–
class EvaConnecter : public QObject {
    Q_OBJECT
public:
    EvaConnecter(EvaNetwork *network);
    ~EvaConnecter();
                                   
    void append(OutPacket *out);
    InPacket *getInPacket();
    const unsigned int numOfOutPackets() const { return outPool.count(); }//现在什么都要搞个pool
    const unsigned int numOfInPackets() const { return inPool.count(); }
    void redirectTo(const int ip, const short port);
    void connect();
        void stop();
    void clientReady();
                                   
        const EvaNetwork::Type getConnectionType() const { return connecter->connectionType(); }
    const QHostAddress getSocketIp();
    const unsigned int getSocketPort();
signals:
    void isReady();
    void networkException(int);
    void packetException(int);
    void sendMessage(int, bool);
    void sendQunMessage(int, bool, QString);//哇。群啊
    void newPacket();
    void clientNotReady();
private:
    bool connectionReady;
    bool isClientSetup;
    QPtrList<InPacket> inPool; //一个poll就是一个链表,ptr-list与直接用list区别在哪里
    QPtrList<OutPacket> outPool;
    QTimer *timer;
    bool isConnected;
    bool isMonitorRunning;
    EvaNetwork *connecter;
                                   
    unsigned char buffer[65535]; //哇。这么大的buffer,存的什么
    unsigned short packetLength;
    unsigned int bufLength;
                                   
    void sendOut( OutPacket *out);
    void removePacket(const int hashCode ); // remove packet which needs acknowlegement,都用到hash了。
    void removeOutRequests(const short cmd);
private slots:
    void isReadySlot();
    void processPacket(char *data, int len);
    void dataCommingSlot(int len);
    void packetMonitor();
    void clearAllPools();
};
#endif

开始接近核心处理逻辑,网络通信等,兴奋ing

/***************************************************************************
 *  Copyright (C) 2004 by yunfan                                          *
 *  yunfan_zg@163.com                                                    *
 *                                                                        *
 *  This program is free software; you can redistribute it and/or modify  *
 *  it under the terms of the GNU General Public License as published by  *
 *  the Free Software Foundation; either version 2 of the License, or    *
 *  (at your option) any later version.                                  *
 *                                                                        *
 *  This program is distributed in the hope that it will be useful,      *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
 *  GNU General Public License for more details.                          *
 *                                                                        *
 *  You should have received a copy of the GNU General Public License    *
 *  along with this program; if not, write to the                        *
 *  Free Software Foundation, Inc.,                                      *
 *  59 Temple Place – Suite 330, Boston, MA  02111-1307, USA.            *
 ***************************************************************************/
         
#include “evaconnecter.h”//哦,又加了这么多头文件
#include “evaqtutil.h”
#include “evahtmlparser.h”
#include “evaimsend.h”
#include “evaqun.h”
#include <qtimer.h>
#include <qmutex.h>//用上了锁,多线程了
#include <arpa/inet.h>
#include <stdlib.h>
#define POOL_CHECK_INTERVAL  2000    /// every 2 second check two pools, 2秒,才检查一次,这么久
EvaConnecter::EvaConnecter(EvaNetwork *network)
{
    memset(buffer, 0, 65535);
    packetLength = 0;
    bufLength = 0;
    connecter = network;
    connectionReady = false;
    isMonitorRunning = false;
    isClientSetup = false;
    QObject::connect(connecter, SIGNAL(isReady()), this, SLOT(isReadySlot()));
    QObject::connect(connecter, SIGNAL(dataComming(int)), this, SLOT(dataCommingSlot(int)));
    QObject::connect(connecter, SIGNAL(exceptionEvent(int)), this, SIGNAL(networkException(int)));
           
        outPool.setAutoDelete(true);
        inPool.setAutoDelete(false);
           
    timer = new QTimer(this);
    QObject::connect(timer, SIGNAL(timeout()), this, SLOT(packetMonitor()));
}
EvaConnecter::~EvaConnecter()
{
    delete connecter;
    if(timer->isActive())
        timer->stop();
    delete timer;
}
void EvaConnecter::append(OutPacket *out)
{
    sendOut(out);  // force to send,这个函数哪里实现的,先清空out buffer,再往send buffer append data
    if(out->needAck()){
        outPool.append(out);
        if(!timer->isActive())    // start out/in pool checking timer
            timer->start(POOL_CHECK_INTERVAL, false);
    }else
        delete out;
}
InPacket *EvaConnecter::getInPacket()
{
    if(inPool.count() <= 0 ){
        emit packetException(-1);
        return NULL;
    }
    return inPool.take();
}
void EvaConnecter::redirectTo(const int ip, const short port)

    inPool.clear();
    outPool.clear();
//http代理,,不是tcp,udp发送??
    if(connecter->connectionType()!= EvaNetwork::HTTP_Proxy){
        connectionReady = false;
        connecter->setServer(QHostAddress(ip), port==-1?connecter->getHostPort():port);
    }else{
        connecter->setServer(connecter->getHostAddress(), connecter->getHostPort());
        connecter->setDestinationServer(QHostAddress(ip).toString(), 443); // always 443 for http proxy, http代理没玩过啊。不懂
          }
    connect();
}
void EvaConnecter::connect()
{
    memset(buffer, 0, 65535);
    packetLength = 0;
    bufLength = 0;
    connecter->connect();
}
void EvaConnecter::stop()
{
    if(timer->isActive())
        timer->stop();
    while(isMonitorRunning);
    //QTimer::singleShot(200, this, SLOT(clearAllPools()));
    clearAllPools();
    memset(buffer, 0, 65535);
    packetLength = 0;
    bufLength = 0;
    connectionReady = false;
    isMonitorRunning = false;
    isClientSetup = false;
    printf(“EvaConnecter stopped \n”);
}
void EvaConnecter::clearAllPools()
{
    while(isMonitorRunning);
    inPool.clear();
    outPool.clear();
}
void EvaConnecter::sendOut( OutPacket *out)
{
    if(timer->isActive())
        timer->stop();
    if(!connectionReady) return;
    unsigned char *buf = (unsigned char *)malloc(MAX_PACKET_SIZE * sizeof(unsigned char));//这个宏,哪里定义的
    int len;
           
    out->fill(buf, &len);
    connecter->write((char *)buf, len);
    free(buf);
    if(!timer->isActive())
        timer->start(POOL_CHECK_INTERVAL, false);
}
void EvaConnecter::removePacket(const int hashCode)
{
    QMutex mutex;
    mutex.lock();
    for( uint i = 0; i < outPool.count(); i++){
        if(outPool.at(i)->hashCode() == hashCode){
            outPool.remove(i);
            –i;
        }
    }
    mutex.unlock();
}
void EvaConnecter::removeOutRequests(const short cmd)
{
    while(isMonitorRunning);
    for( uint i = 0; i < outPool.count(); i++){
        if(outPool.at(i)->getCommand() == cmd){
            outPool.remove(i);//packet里面有个cmd字段
            –i;
        }
    }
}
void EvaConnecter::isReadySlot()
{
    connectionReady = true;
    emit isReady();//这不是死循环吗?信号–槽–信号
}
void EvaConnecter::dataCommingSlot(int len)
{
    char *rawData = new char[len+1];
    if(!connecter->read(rawData, len)){
        fprintf(stderr, “–Eva Connecter: Bytes read wrong!\n”);
        return;
    }
    if(connecter->connectionType() != EvaNetwork::UDP){
        memcpy(buffer+bufLength, rawData, len);
        bufLength += len;
        delete []rawData;
        unsigned short tmp;
        memcpy(&tmp, buffer, 2);
        packetLength = ntohs(tmp);
//操作了这么多,到底干了什么?
        while(bufLength >= packetLength){
            rawData = new char[packetLength];
            memcpy(rawData, buffer, packetLength);
            memcpy(buffer, buffer + packetLength, bufLength – packetLength);
            len = packetLength;
            bufLength -=packetLength;
            processPacket(rawData, len);//最后还是这个函数处理
            delete []rawData;
            if(!bufLength)  break;
            memcpy(&tmp, buffer, 2);
            packetLength = ntohs(tmp);
        }
               
               
    }else{
        processPacket(rawData, len);//这个是udp处理。。
        delete []rawData;
    }
}
void EvaConnecter::processPacket( char * data, int len )
{
    InPacket *packet = new InPacket((unsigned char *)data, len);
    if(!packet->getLength()){
        printf(“Bad packet, ignore it\n”);
        delete packet;
        return;
    }
        removePacket(packet->hashCode());
      //心动包啊。。这个只是用户端,服务端在哪里?
    if(packet->getCommand() == QQ_CMD_KEEP_ALIVE)
        removeOutRequests(QQ_CMD_KEEP_ALIVE);
        //为何直接移除了 
    if(packet->getCommand() == QQ_CMD_GET_FRIEND_ONLINE)
        removeOutRequests(QQ_CMD_GET_FRIEND_ONLINE);
               
        inPool.append(packet);
    if(isClientSetup || (!isClientSetup && packet->getCommand()!= QQ_CMD_RECV_IM &&
                packet->getCommand()!= QQ_CMD_RECV_MSG_FRIEND_CHANGE_STATUS))
        emit newPacket();
    else if(!isClientSetup)
        emit clientNotReady();
}
void EvaConnecter::packetMonitor()
{
    if(!connectionReady)  return;
    if(isMonitorRunning) return;
    isMonitorRunning = true;
    for ( uint i=0;  i < outPool.count(); i++ ){
        if(outPool.at(i)->needResend()){
            sendOut(outPool.at(i));
        }else{
            short cmd = outPool.at(i)->getCommand();
            isMonitorRunning = false;
            if(cmd == QQ_CMD_SEND_IM){
                SendIM *im = dynamic_cast<SendIM *>(outPool.at(i));
                if(im)
                    emit sendMessage(im->getReceiver(), false);
                else
                    emit packetException( cmd);
            } else if( cmd == QQ_CMD_QUN_CMD ){
                    QunPacket *qun = dynamic_cast<QunPacket *>(outPool.at(i));
                    if(qun){
                        char qunCmd = qun->getQunCommand();
                        if(qunCmd == QQ_QUN_CMD_SEND_IM || qunCmd == QQ_QUN_CMD_SEND_IM_EX)
                            emit sendQunMessage(qun->getQunID(), false, QString::null);
                        else
                            emit packetException(cmd);
                    } else
                        emit packetException(cmd);
                } else
                    emit packetException(cmd);
            if(!connectionReady)  return;
            if(!isMonitorRunning) return;
            removePacket(outPool.at(i)->hashCode());
            if(!outPool.count() && !inPool.count() && timer)    timer->stop();
            return;
        }
    }
    if(isClientSetup && inPool.count()>0){
        emit newPacket();
    }
    if(!outPool.count() && !inPool.count() && timer)    timer->stop();
    isMonitorRunning = false;
}
void EvaConnecter::clientReady( )
{
    isClientSetup = true;
    while(inPool.count())
        emit newPacket();
}
const QHostAddress EvaConnecter::getSocketIp( )
{
    if(connecter) return connecter->getSocketIp();
    return QHostAddress();
}
const unsigned int EvaConnecter::getSocketPort( )
{
    if(connecter) return connecter->getSocketPort();
    return 0;
}

不错,越来越深入,,22:30,做几个俯卧撑,继续

/***************************************************************************
 *  Copyright (C) 2004 by yunfan                                          *
 *  yunfan_zg@163.com                                                    *
 *                                                                        *
 *  This program is free software; you can redistribute it and/or modify  *
 *  it under the terms of the GNU General Public License as published by  *
 *  the Free Software Foundation; either version 2 of the License, or    *
 *  (at your option) any later version.                                  *
 *                                                                        *
 *  This program is distributed in the hope that it will be useful,      *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
 *  GNU General Public License for more details.                          *
 *                                                                        *
 *  You should have received a copy of the GNU General Public License    *
 *  along with this program; if not, write to the                        *
 *  Free Software Foundation, Inc.,                                      *
 *  59 Temple Place – Suite 330, Boston, MA  02111-1307, USA.            *
 ***************************************************************************/
#ifndef EVANETWORK_H
#define EVANETWORK_H
#include <qobject.h>
#include <qhostaddress.h>
class EvaSocket;
class EvaHttpProxy;
class EvaNetwork : public QObject{
    Q_OBJECT
public:
    enum Type { UDP, TCP, HTTP_Proxy}; //3种方式,可以好好看看http代理,这方面技术没研究过
    enum Event { Init, Connecting, Ready, Failed, None, BytesReadWrong,
            Proxy_None, Proxy_TCP_Ready, Proxy_Connecting, Proxy_Ready,
                Proxy_Need_Auth, Proxy_Read_Error, Proxy_Error  };
    EvaNetwork(const QHostAddress &host, const short port, const Type type = UDP);//默认是udp
    ~EvaNetwork();
    //哦。有server,那么服务器部分的程序,有吗 
    void setServer(const QHostAddress &address, const short port);
    const QHostAddress &getHostAddress() const;  // if it’s Http Proxy, return the proxy’s address
    const short getHostPort() const;
                                         
    void setDestinationServer(const QString &server, const short port); // for Http Proxy only;
        void setAuthParameter(const QString &username, const QString &password);//代理认证?
    void setAuthParameter(const QCString &param);
    void newURLRequest();
    void connect();
                                         
    bool read(char *buf, int len);
    bool write(const char *buf, const int len);
    void setWriteNotifierEnabled(bool enabled);
    void close();
    const Type connectionType() { return type; }
    const QHostAddress getSocketIp();
    const unsigned int getSocketPort();
signals:
    void isReady();
    void dataComming(int);
    void exceptionEvent(int); // all in enum type Event;
    void writeReady();
private:
    EvaSocket *socket; //基本socket
    Type type;
private slots:
    void processProxyEvent(int);
};
#endif

 /*********************************************************************

 

继续看cpp文件

/***************************************************************************
 *  Copyright (C) 2004 by yunfan                                          *
 *  yunfan_zg@163.com                                                    *
 *                                                                        *
 *  This program is free software; you can redistribute it and/or modify  *
 *  it under the terms of the GNU General Public License as published by  *
 *  the Free Software Foundation; either version 2 of the License, or    *
 *  (at your option) any later version.                                  *
 *                                                                        *
 *  This program is distributed in the hope that it will be useful,      *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
 *  GNU General Public License for more details.                          *
 *                                                                        *
 *  You should have received a copy of the GNU General Public License    *
 *  along with this program; if not, write to the                        *
 *  Free Software Foundation, Inc.,                                      *
 *  59 Temple Place – Suite 330, Boston, MA  02111-1307, USA.            *
 ***************************************************************************/
                 
#include “evanetwork.h”
#include “evasocket.h”
                 
EvaNetwork::EvaNetwork(const QHostAddress &host, const short port, const Type type)
    :socket(NULL)
{
    this->type = type;
    switch(type){
    case UDP:
        socket = new EvaSocket(host, port);  // default is UDP
        QObject::connect(socket, SIGNAL(isReady()), this, SIGNAL(isReady()));//socket—>this
        QObject::connect(socket, SIGNAL(writeReady()), SIGNAL(writeReady()));
        QObject::connect(socket, SIGNAL(receivedData(int)), this, SIGNAL(dataComming(int)));
        QObject::connect(socket, SIGNAL(exceptionEvent(int)), this, SLOT(processProxyEvent(int)));
        break;
    case TCP:
        socket = new EvaSocket(host, port, EvaSocket::TCP);
        QObject::connect(socket, SIGNAL(isReady()), this, SIGNAL(isReady()));
        QObject::connect(socket, SIGNAL(writeReady()), SIGNAL(writeReady()));
        QObject::connect(socket, SIGNAL(receivedData(int)), this, SIGNAL(dataComming(int)));
        QObject::connect(socket, SIGNAL(exceptionEvent(int)), this, SLOT(processProxyEvent(int)));
        break;
    case HTTP_Proxy:
        socket = new EvaHttpProxy(host, port);
        QObject::connect(socket, SIGNAL(proxyWriteReady()), SIGNAL(writeReady()));
        QObject::connect(socket, SIGNAL(proxyEvent(int)), this, SLOT(processProxyEvent(int)));
        QObject::connect(socket, SIGNAL(dataArrived(int)), this, SIGNAL(dataComming(int)));
        QObject::connect(socket, SIGNAL(socketException(int)), this, SIGNAL(exceptionEvent(int)));
        break;
    default:
        socket = new EvaSocket(host, port);  // default is UDP
        break;
    }
}
EvaNetwork::~EvaNetwork()
{
    if(socket) delete socket;
}
                 
void EvaNetwork::setServer(const QHostAddress &address, const short port)
{
    socket->setHost(address, port); 
}
const QHostAddress &EvaNetwork::getHostAddress() const
{
    return socket->getHostAddress();
}
const short EvaNetwork::getHostPort() const
{
    return socket->getHostPort();
}
void EvaNetwork::setDestinationServer(const QString &server, const short port) // for Http Proxy only;
{
    if(type != HTTP_Proxy) return;
    //看来在这个类EvaHttpProxy里,实现了http代理,得详细看看
    ((EvaHttpProxy*)(socket))->setDestinationServer(server, port);
}
void EvaNetwork::setAuthParameter(const QString &username, const QString &password)
{
    ((EvaHttpProxy*)(socket))->setAuthParameter(username, password);
}
void EvaNetwork::setAuthParameter(const QCString &param)
{
    ((EvaHttpProxy*)(socket))->setBase64AuthParam(param);
}
void EvaNetwork::newURLRequest()
{
    ((EvaHttpProxy*)(socket))->tcpReady();
}
void EvaNetwork::connect()
{
    socket->startConnecting();
}
bool EvaNetwork::read(char *buf, int len)
{
    return socket->read(buf, len);
}
bool EvaNetwork::write(const char *buf, const int len)
{
    return socket->write(buf, len);
}
//什么东西都是socket实现的,这里只是封装了一下
void EvaNetwork::setWriteNotifierEnabled(bool enabled)
{
    socket->setWriteNotifierEnabled(enabled);
}
void EvaNetwork::processProxyEvent(int num)
{
    if(type != HTTP_Proxy){
        switch(num){
        case EvaSocket::Init:
        case EvaSocket::Connecting:
        case EvaSocket::Ready:
        case EvaSocket::Failed:
        case EvaSocket::None:
        case EvaSocket::BytesReadWrong:
            emit exceptionEvent(num);
            break;
        }
        }else{
            switch(num){
        case EvaHttpProxy::Proxy_None:
        case EvaHttpProxy::Proxy_TCP_Ready:
        case EvaHttpProxy::Proxy_Connecting:
            break;
        case EvaHttpProxy::Proxy_Ready:
            emit isReady();
            break;
        case EvaHttpProxy::Proxy_Need_Auth:
            emit exceptionEvent(Proxy_Need_Auth);
            break;
        case EvaHttpProxy::Proxy_Read_Error:
            emit exceptionEvent(Proxy_Read_Error);
            break;
        case EvaHttpProxy::Proxy_Error:
            emit exceptionEvent(Proxy_Error);
            break;
        }
        }
}
void EvaNetwork::close( )
{
    socket->closeConnection();
}
const QHostAddress EvaNetwork::getSocketIp( )
{
    if(socket) return socket->getSocketAddress();
    return QHostAddress();
}
const unsigned int EvaNetwork::getSocketPort( )
{
    if(socket) return socket->getSocketPort();
    return 0;
}

 

还是没啥具体实现,还是继续找最底层的socket函数

/***************************************************************************
 *  Copyright (C) 2004 by yunfan                                          *
 *  yunfan_zg@163.com                                                    *
 *                                                                        *
 *  This program is free software; you can redistribute it and/or modify  *
 *  it under the terms of the GNU General Public License as published by  *
 *  the Free Software Foundation; either version 2 of the License, or    *
 *  (at your option) any later version.                                  *
 *                                                                        *
 *  This program is distributed in the hope that it will be useful,      *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
 *  GNU General Public License for more details.                          *
 *                                                                        *
 *  You should have received a copy of the GNU General Public License    *
 *  along with this program; if not, write to the                        *
 *  Free Software Foundation, Inc.,                                      *
 *  59 Temple Place – Suite 330, Boston, MA  02111-1307, USA.            *
 ***************************************************************************/
#ifndef EVASERVERS_H
#define EVASERVERS_H
#include <qobject.h>
#include <qvaluelist.h> //qt这么多奇怪的list
#include <qhostaddress.h>
/**
This class loads all Tencent’s tcp and udp servers, and return a random server IP address
This class also involves some DNS operations.
看样子,是直接用qq的服务器,他从哪里知道的qq的服务器,还能有dns操作。未接触的知识
@author yunfan
*/
class QDns;
class EvaServers : public QObject
{
    Q_OBJECT
public:
    EvaServers(QString &dataRoot);
               
    virtual ~EvaServers();
    void fetchAddress(bool isUdp);
signals:
    void isReady(QHostAddress ip);
private:
    typedef struct serverItem{
        int type; 
        QString addr;
    } serverItem;
               
    enum { UDP, TCP, Addr_URL, Addr_IP};
               
    QString filename;
    bool gotIP;
    bool isLoaded;
    int fetchType;
    QDns *dns; //qt还有dns类。无所不能
    QValueList<serverItem> TCPServers;
    QValueList<serverItem> UDPServers;
               
    bool loadServers();
    void defaultAddress();
private slots:
    void getResultsSlot();
};
#endif

/***************************************************************************
 *  Copyright (C) 2004 by yunfan                                          *
 *  yunfan_zg@163.com                                                    *
 *                                                                        *
 *  This program is free software; you can redistribute it and/or modify  *
 *  it under the terms of the GNU General Public License as published by  *
 *  the Free Software Foundation; either version 2 of the License, or    *
 *  (at your option) any later version.                                  *
 *                                                                        *
 *  This program is distributed in the hope that it will be useful,      *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
 *  GNU General Public License for more details.                          *
 *                                                                        *
 *  You should have received a copy of the GNU General Public License    *
 *  along with this program; if not, write to the                        *
 *  Free Software Foundation, Inc.,                                      *
 *  59 Temple Place – Suite 330, Boston, MA  02111-1307, USA.            *
 ***************************************************************************/
#include “evaservers.h”
#include <qdns.h>
#include <qfile.h>
#include <qdatastream.h>
#include <qdatetime.h>  // seed for rand()
#include <stdlib.h>      // rand() function
EvaServers::EvaServers(QString &dataRoot):
    gotIP(FALSE),
    isLoaded(FALSE)
{
    filename = dataRoot + “/servers”;
    QTime t = QTime::currentTime();
    srand( t.hour()*12+t.minute()*60+t.second()*60 );
    isLoaded = this->loadServers();
    dns = NULL;
}
EvaServers::~EvaServers()
{
    delete dns;
}
void EvaServers::fetchAddress( bool isUdp )
{
    int num = 0;
    if(isUdp){
      num = UDPServers.count();
      fetchType = UDP;
    } else{
      num = TCPServers.count();
      fetchType = TCP;
    }
    if(num == 0 ){
        defaultAddress();
        return;
    }
    int index = rand() % num;
    serverItem addr;
    if(isUdp)
      addr = UDPServers[index];
    else
      addr = TCPServers[index];
       
    if(addr.type == Addr_IP){
        emit isReady(QHostAddress(addr.addr.latin1())); // this way, Red Hat 9 might work properly
        return;
    }
     
    // the address should be a URL now, so we try to get the IP         
    if(dns!=NULL) {
        QObject::disconnect(dns, 0,0,0);
        delete dns;
    }
    dns =  new QDns(addr.addr, QDns::A);   
    QObject::connect(dns, SIGNAL(resultsReady()), this, SLOT(getResultsSlot()));
}
bool EvaServers::loadServers( )
{
    QFile file(filename);   
    if(!file.open(IO_ReadOnly)){
            return FALSE;
    }
       
    QTextStream stream(&file);
    QString line;
    QStringList lineList;
    int nextType = 0;
    while(!stream.atEnd()){
        line = stream.readLine().stripWhiteSpace();
        if(line == “UDP”){
            nextType = UDP;
            continue;
        }else if(line == “TCP”){
            nextType = TCP;
            continue;
        } else if(line == “” ){
            //nextType = 0;
            continue;
            }
                   
        lineList = QStringList::split(“:”, line);
       
        if(lineList.size() != 2)
          continue;
        lineList[0].stripWhiteSpace();
                           
        serverItem *item = new serverItem();   
        if(lineList[0]==”URL”){       
            item->type = Addr_URL;               
        }else if(lineList[0]==”IP”){
            item->type = Addr_IP;
        }else
            continue;
           
        item->addr = lineList[1].stripWhiteSpace();
           
        if(nextType == UDP){
            UDPServers.append(*item);//从file里面获得server地址列表
        }
           
        if(nextType == TCP){
            TCPServers.append(*item);
        }
    }
       
    file.close();
    return TRUE; 
}
void EvaServers::defaultAddress()
{   
    if(fetchType == TCP){
        emit isReady(QHostAddress(“218.17.209.23”)); //这个是缺省地址。
    }else{
        emit isReady(QHostAddress(“218.17.209.20”)); //又是tcp又是udp,腾讯真正的是怎么个逻辑通信的? 
    }   
}
void EvaServers::getResultsSlot( )
{
    QValueList<QHostAddress> list = dns->addresses();//域名解析出来ip地址
    if(list.count() == 0 ){
        defaultAddress();
        return;
    }
       
    QHostAddress addr = list[0];
    emit isReady(addr);
}

管中窥豹啊。

/***************************************************************************
 *  Copyright (C) 2004 by yunfan                                          *
 *  yunfan_zg@163.com                                                    *
 *                                                                        *
 *  This program is free software; you can redistribute it and/or modify  *
 *  it under the terms of the GNU General Public License as published by  *
 *  the Free Software Foundation; either version 2 of the License, or    *
 *  (at your option) any later version.                                  *
 *                                                                        *
 *  This program is distributed in the hope that it will be useful,      *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
 *  GNU General Public License for more details.                          *
 *                                                                        *
 *  You should have received a copy of the GNU General Public License    *
 *  along with this program; if not, write to the                        *
 *  Free Software Foundation, Inc.,                                      *
 *  59 Temple Place – Suite 330, Boston, MA  02111-1307, USA.            *
 ***************************************************************************/
#ifndef EVASOCKET_H
#define EVASOCKET_H
#include <qhostaddress.h>
#include <qcstring.h>  //cstring,,这么多没用过的类
#include <qobject.h>
// Implementing UDP & TCP connections to Tencent Server
class QSocketDevice;
class QSocketNotifier;
                     
class EvaSocket : public QObject {//这个socket类,也包括http?
    Q_OBJECT
public:
    enum Type { TCP, UDP};
    enum Status { Init, Connecting, Ready, Failed, None, BytesReadWrong};
    EvaSocket(const QHostAddress &host, const short port, const Type type = UDP);
    ~EvaSocket();
                       
    const Type getConnectType() const { return connectionType; }
                           
    void setHost( const QHostAddress &address, const short port);
    const QHostAddress &getHostAddress() const { return server; }
    const short getHostPort() const { return serverPort; }
    const Status getStatus() const { return connectionStatus; }
                       
    void closeConnection();
    void startConnecting();
    bool write(const char *buf, const int len);
    bool read(char *buf, int len);
    const QHostAddress getSocketAddress();
    const unsigned short getSocketPort();
    void setWriteNotifierEnabled(bool enabled);
signals:
    void isReady(); // emit when socket is connected
    void receivedData(int);    // emit after receiving data from server
    void exceptionEvent(int);      // emit whenever exception happens
    void writeReady();
protected:
    QSocketDevice *connectSocket;
    QSocketNotifier *socketReadNotifier;
    QSocketNotifier *socketWriteNotifier;
                       
    int receivedLength;
    char *receivedBuffer;
private:
    Type connectionType;
    QHostAddress server;
    short serverPort;
                       
    Status connectionStatus;  //  connected or not
private slots:
    void slotWriteReady(int);
    void slotReceiveReady(int);
};
// call read after receiving proxyEvent(Proxy_Ready) SIGNAL
class EvaHttpProxy : public EvaSocket {//基于socket
    Q_OBJECT
public:
    enum ProxyStatus { Proxy_None, Proxy_TCP_Ready, Proxy_Connecting, Proxy_Ready,
                Proxy_Need_Auth, Proxy_Read_Error, Proxy_Error};
    EvaHttpProxy(const QHostAddress &proxyHost, const short proxyPort, const QString username = QString::null,
                                const QString password = QString::null);
    void setDestinationServer(const QString &server, const int port); // server could be IP or URL
    const QString &getDestinationServer() const { return destinationAddress; }
    void setAuthParameter(const QString &username, const QString &password);
    const QCString &getBase64AuthParam() const { return base64AuthParam;}//主要就是进行了一些认证
    void setBase64AuthParam(const QCString &param) { base64AuthParam = param;  status = Proxy_None; }
    bool doInitConnecting();
    bool doAuthConnecting();
                       
    const ProxyStatus getProxyStatus() const { return status; }
signals:
    void dataArrived(int);
    void proxyEvent( int );
    void socketException(int);
    void proxyWriteReady();
public slots:
    void tcpReady();
    void slotWriteReady();
private:
    ProxyStatus status;
    QString destinationAddress;
    QCString base64AuthParam;
    QCString sentBuffer;
    char *readBuffer;
    void received(int len);
private slots:
    void parseData(int len);
};
#endif

 

/***************************************************************************
 *  Copyright (C) 2004-2005 by yunfan                                    *
 *  yunfan_zg@163.com                                                    *
 *                                                                        *
 *  This program is free software; you can redistribute it and/or modify  *
 *  it under the terms of the GNU General Public License as published by  *
 *  the Free Software Foundation; either version 2 of the License, or    *
 *  (at your option) any later version.                                  *
 *                                                                        *
 *  This program is distributed in the hope that it will be useful,      *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
 *  GNU General Public License for more details.                          *
 *                                                                        *
 *  You should have received a copy of the GNU General Public License    *
 *  along with this program; if not, write to the                        *
 *  Free Software Foundation, Inc.,                                      *
 *  59 Temple Place – Suite 330, Boston, MA  02111-1307, USA.            *
 ***************************************************************************/
#include “evasocket.h”
#include “qmdcodec.h”    //待研究
#include <stdlib.h>
#include <qsocketdevice.h>
#include <qsocketnotifier.h>
#include <qapplication.h>
#include <qmutex.h>
#include <qtimer.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/mman.h>    //干嘛的
/*!
    \class EvaSocket evasocket.h
    \brief The EvaSocket class provides a UDP or TCP connection  看来不包含http
             
    It provides a very simple non-blocking socket connection.
    socketWriteNotifier is only used once to notify that the connection is ready
    to write, after isReady() emited, socketWriteNotifier is disabled unless
    setHost() is called.
 */
EvaSocket::EvaSocket(const  QHostAddress &host, const short port, const Type type)
    : socketReadNotifier(NULL), socketWriteNotifier(NULL)
{
    connectionStatus = None;
    receivedLength = 0;
    receivedBuffer = NULL;
    connectionType = type;
        server = host;
    serverPort = port;
    if(connectionType == UDP){
        connectSocket = new QSocketDevice(QSocketDevice::Datagram);  //udp被当成device,qt这么认为
    }else{
        connectSocket = new QSocketDevice(QSocketDevice::Stream);
        connectSocket->setBlocking(false);
            socketWriteNotifier =  new QSocketNotifier(connectSocket->socket(),
                            QSocketNotifier::Write,0,”writeNotifier”);  //写通知,这个是基于epoll?select?poll?
        QObject::connect(socketWriteNotifier,SIGNAL(activated(int)),SLOT(slotWriteReady(int)));
        socketWriteNotifier->setEnabled(false);
    }
    socketReadNotifier = new QSocketNotifier(connectSocket->socket(),
                        QSocketNotifier::Read,0,”readNotifier”);
    connectionStatus = Init;
    QObject::connect(socketReadNotifier,SIGNAL(activated(int)),SLOT(slotReceiveReady(int)));
    socketReadNotifier->setEnabled(false);
}
EvaSocket::~EvaSocket()
{
    delete connectSocket;
    if(socketReadNotifier) {
        socketReadNotifier->setEnabled(false);
        delete socketReadNotifier;
    }
    if(socketWriteNotifier) {
        socketWriteNotifier->setEnabled(false);
        delete socketWriteNotifier;
    }
}
const QHostAddress EvaSocket::getSocketAddress( )
{
    if(connectSocket) return connectSocket->address();
    return QHostAddress();
}
const unsigned short EvaSocket::getSocketPort( )
{
    if(connectSocket) return connectSocket->port();
    return 0;
}
void EvaSocket::setHost(const QHostAddress &address, const short port)
{
    server = address;
    serverPort = port; 
    connectionStatus = None;
    if(connectSocket->isValid()){
        delete connectSocket;
        if(socketReadNotifier) {
            socketReadNotifier->setEnabled(false);
            delete socketReadNotifier;
        }
        if(socketWriteNotifier) {
            socketWriteNotifier->setEnabled(false);
            delete socketWriteNotifier;
        }
        if(connectionType == UDP){
            connectSocket = new QSocketDevice(QSocketDevice::Datagram);
        }else{
            connectSocket = new QSocketDevice(QSocketDevice::Stream);
            connectSocket->setBlocking(false);
            socketWriteNotifier =  new QSocketNotifier(connectSocket->socket(),
                                QSocketNotifier::Write,0,”writeNotifier”);
            QObject::connect(socketWriteNotifier,SIGNAL(activated(int)),SLOT(slotWriteReady(int)));
            socketWriteNotifier->setEnabled(false);
        }
        socketReadNotifier = new QSocketNotifier(connectSocket->socket(),
                            QSocketNotifier::Read,0,”SocketNotifier”);
        QObject::connect(socketReadNotifier,SIGNAL(activated(int)),SLOT(slotReceiveReady(int)));
        if(connectionType == TCP)
            socketReadNotifier->setEnabled(false);
    }
    connectionStatus = Init;
}
void EvaSocket::closeConnection()
{
    if(connectSocket->isOpen()) connectSocket->close();
    connectionStatus = None;
    receivedLength = 0;
}
void EvaSocket::startConnecting()
{
    if(connectionStatus != Init) {
        emit exceptionEvent(connectionStatus);
        return;
    }
    connectionStatus = Connecting;
    if(connectionType == TCP){
        if(!connectSocket->connect(server, serverPort)){
            fprintf(stderr,”connecting server failed\nError type: “);
            connectionStatus = Failed;
            switch(connectSocket->error()){
                case QSocketDevice::NoError:
                    fprintf(stderr,”NoError\n”);
                    break;
                case QSocketDevice::AlreadyBound:
                    fprintf(stderr,”AlreadyBound\n”);
                    break;
                case QSocketDevice::Inaccessible:
                    fprintf(stderr,”Inaccessible\n”);
                    break;
                case QSocketDevice::NoResources:
                    fprintf(stderr,”NoResources\n”);
                    break;
                case QSocketDevice::InternalError:
                    fprintf(stderr,”InternalError\n”);
                    break;
                case QSocketDevice::Impossible:
                    fprintf(stderr,”Impossible\n”);
                    break;
                case QSocketDevice::NoFiles:
                    fprintf(stderr,”NoFiles\n”);
                    break;
                case QSocketDevice::ConnectionRefused:
                    fprintf(stderr,”ConnectionRefused\n”);
                    break;
                case QSocketDevice::NetworkFailure:
                    fprintf(stderr,”NetworkFailure\n”);
                    break;
                case QSocketDevice::UnknownError:
                    fprintf(stderr,”UnknownError\n”);
                    break;
                default:
                    printf(“not listed error\n”);
            }
            emit exceptionEvent(connectionStatus);
            return;
        }
    }
    if(socketReadNotifier) socketReadNotifier->setEnabled(true);
    if(connectionType == TCP && socketWriteNotifier) {
        socketWriteNotifier->setEnabled(true);
    }else{
        connectionStatus = Ready;
        emit isReady();
    }
}
bool EvaSocket::write(const char *buf, const int len)
{
    if(connectionStatus != Ready || !buf ) return false;
    if(!connectSocket->isValid()){
        if(connectionType == TCP && socketReadNotifier && socketWriteNotifier){
            socketReadNotifier->setEnabled(false);
            socketWriteNotifier->setEnabled(false);
        }
        emit exceptionEvent(Failed);
        return false;
    }
    QMutex mutex; //写之前,锁一下?锁什么?
    mutex.lock();
    int BytesSent = 0;
    if(socketWriteNotifier) socketWriteNotifier->setEnabled(false);
    if(connectionType == UDP){
        BytesSent =connectSocket->writeBlock(buf, len, server, serverPort);
    }else{
        int bytes = 0;
        int times = 0;
//      printf(“—++++++++–  EvaSocket::write — BytesSent:%d, len: %d\n”, BytesSent, len);
        while(BytesSent < len){
            bytes =connectSocket->writeBlock(buf + BytesSent, len – BytesSent);
            if(bytes == -1) {
                printf(“EvaSocket::write retry :%d\n”, times);
                if(!connectSocket->error()){
                    if(times>20){
                        fprintf(stderr, “EvaSocket::write — error : retried %d times\n”, times);
                        mutex.unlock();
                        return false;
                    }
                    usleep(10000);
                    //qApp->processEvents();
                    times++;
                    continue;
                }else
                    break;
            }
            BytesSent += bytes;
//          while( connectionStatus != WriteReady && BytesSent < len ){
//              qApp->processEvents();
//              usleep(10 * 1000);
//              if(!connectSocket->isValid()){
//                  connectionStatus = oldStatus;
//                  mutex.unlock();
//                  return false;
//              }
//          }
//          printf(”                — EvaSocket::write — bytes:%d, len: %d\n”, bytes, len);
        }
//      printf(”                EvaSocket::write — BytesSent:%d, len: %d\n”, BytesSent, len);
    }
    mutex.unlock();
    if(len != BytesSent){
        printf(“EvaSocket::write — error code: %d\n”, connectSocket->error());
        return false;
    }
    return true;
}
bool EvaSocket::read(char *buf, int len)
{
    if(connectionStatus != Ready || receivedLength != len || !buf ){
        printf(“EvaSocket::read — receivedLength: %d, len: %d\n”, receivedLength, len);
        return false;
    }
    memcpy(buf, receivedBuffer, receivedLength);
    if(socketReadNotifier) socketReadNotifier->setEnabled(true);
    return true;
}
void EvaSocket::setWriteNotifierEnabled( bool enabled )
{
    if(socketWriteNotifier) socketWriteNotifier->setEnabled(enabled);
}
void EvaSocket::slotWriteReady(int /*socket */)
{
    if(socketWriteNotifier) socketWriteNotifier->setEnabled(false);
    if(connectionStatus == Connecting){
        connectionStatus = Ready;
        emit isReady();
    } else{
        emit writeReady();
    }
}
void EvaSocket::slotReceiveReady(int /*socket*/)
{
    if( (socketReadNotifier->type() != QSocketNotifier::Read) || (!connectSocket->isValid()) ){
        socketReadNotifier->setEnabled(false);
        printf(“EvaSocket::slotReceiveReady — socket not valid or notifier not set to Read \n”);
        emit exceptionEvent(Failed);
        return;
    }
                 
    int ByteCount = 0;
    ByteCount = connectSocket->bytesAvailable();
             
    if(receivedBuffer!=NULL) delete receivedBuffer;
    receivedBuffer = new char[ByteCount * 2]; 
    //read都不锁,write锁的什么
    receivedLength = connectSocket->readBlock(receivedBuffer,ByteCount*2);
    if(!receivedLength){
        printf(“EvaSocket::slotReceiveReady — connection closed due to ZERO byte\n”);
        socketReadNotifier->setEnabled(false);//不停的开关这个通知
        emit exceptionEvent(Failed);
        return;
    }
             
    if(receivedLength == -1){
        printf(“EvaSocket::slotReceiveReady — readBlock return -1\n”);
        emit exceptionEvent(Failed);
        return;
    }
    if(socketReadNotifier) socketReadNotifier->setEnabled(false);
    emit receivedData(receivedLength);
    if(receivedLength != ByteCount)
        printf(“EvaSocket::slotReceiveReady — bytesAvailable() might not be accurate.\n”);
}
/* =========================================================== */
EvaHttpProxy::EvaHttpProxy(const QHostAddress &proxyHost, const short proxyPort, const QString username, const QString password)
    : EvaSocket(proxyHost, proxyPort, EvaSocket::TCP),
    status(Proxy_None),
    destinationAddress(“”),
    base64AuthParam(“”),
    readBuffer(NULL)
{
    if(username!=QString::null && password!= QString::null){
        setAuthParameter(username, password);
    }
    QObject::connect(this, SIGNAL(isReady()), SLOT(tcpReady()));
    QObject::connect(this, SIGNAL(writeReady()), SLOT(slotWriteReady()));
    QObject::connect(this, SIGNAL(receivedData(int)), SLOT(parseData(int)));
    QObject::connect(this, SIGNAL(exceptionEvent(int)), SIGNAL(socketException(int)));
}
void EvaHttpProxy::setDestinationServer(const QString &server, const int port) // server could be IP or URL
{
    destinationAddress = server + ‘:’ + QString::number(port);// qq http proxy server port: 443,改成规定的格式
    status = Proxy_None;
}
void EvaHttpProxy::setAuthParameter(const QString &username, const QString &password)
{
    QCString para = (username + ‘:’ + password).local8Bit(); //规定的格式,QString?qt帮助里看不到这个类
    base64AuthParam = QCodecs::base64Encode(para);//这是个什么code?QTextCodec?
    status = Proxy_None;
}
bool EvaHttpProxy::doInitConnecting()
{
    if(getStatus() != EvaSocket::Ready) return false;
    if(destinationAddress == “”) return false;
        //这个是关键的格式,哪里知道的
    sentBuffer = “CONNECT ” + destinationAddress.local8Bit() + ” HTTP/1.1\r\n” +
        “Accept: */*\r\n” + “Content-Type: text/html\r\nProxy-Connection: Keep-Alive\r\n” +
        “Content-length: 0\r\n\r\n”;
    status = Proxy_Connecting;
    return write(sentBuffer.data(), sentBuffer.length());
}
bool EvaHttpProxy::doAuthConnecting()
{
    if(getStatus() != EvaSocket::Ready) return false;
    if(destinationAddress == “”) return false;
    if(base64AuthParam == “”) return false;
             
    sentBuffer = “CONNECT ” + destinationAddress.local8Bit() + ” HTTP/1.1\r\n” +
        “Proxy-Authorization: Basic ” + base64AuthParam + “\r\n” +
        “Accept: */*\r\nContent-Type: text/html\r\nProxy-Connection: Keep-Alive\r\n” +
        “Content-length: 0\r\n\r\n”;
    status = Proxy_Connecting;
    return write(sentBuffer.data(), sentBuffer.length());
}
void EvaHttpProxy::tcpReady()
{
    printf(“EvaHttpProxy::tcpReady — TCP connection ready\n”);
    if(destinationAddress == “”) {
        emit proxyEvent(Proxy_TCP_Ready);
        return;
    }
             
    if(base64AuthParam != “”)
        doAuthConnecting();
    else
        doInitConnecting();
}
void EvaHttpProxy::slotWriteReady()
{
    if ( status == Proxy_Ready )
        emit proxyWriteReady();
}
void EvaHttpProxy::parseData(int len)

    if(readBuffer!=NULL) free(readBuffer);
    readBuffer = (char *)malloc((len+1) * sizeof(char));
    if(!read(readBuffer, len)){
        emit proxyEvent(Proxy_Read_Error);
        return;
    }
    readBuffer[len]=0x00;
    QString replyBuffer(readBuffer);
    if(replyBuffer.startsWith(“HTTP/1.”)){ // this is for RedHat 9, the old Qt dosen’t support QString::startsWith(const QString &str, bool cs) const
        int replyCode = replyBuffer.mid(9, 3).toInt();
        fprintf(stderr, “Proxy Server Reply Code: %d\n”,replyCode);
        switch(replyCode){
        case 200:
            status = Proxy_Ready;
            emit proxyEvent(Proxy_Ready);
            break;
        case 407:
            status = Proxy_Need_Auth;
            emit proxyEvent(Proxy_Need_Auth);
            break;
        case 501:  // “Not Support”
        case 502:  // “Proxy Error”
        default:
            status = Proxy_Error;
            emit proxyEvent(Proxy_Error);
            break;
        }
        return;
    }
    if(status == Proxy_Ready)
        dataArrived(len);
}

 

越看问题越多啊,难道这些用的是qt很早之前的版本,很多类,根本找不到。应该是。

/***************************************************************************
 *  Copyright (C) 2004 by yunfan                                          *
 *  yunfan_zg@163.com                                                    *
 *                                                                        *
 *  This program is free software; you can redistribute it and/or modify  *
 *  it under the terms of the GNU General Public License as published by  *
 *  the Free Software Foundation; either version 2 of the License, or    *
 *  (at your option) any later version.                                  *
 *                                                                        *
 *  This program is distributed in the hope that it will be useful,      *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
 *  GNU General Public License for more details.                          *
 *                                                                        *
 *  You should have received a copy of the GNU General Public License    *
 *  along with this program; if not, write to the                        *
 *  Free Software Foundation, Inc.,                                      *
 *  59 Temple Place – Suite 330, Boston, MA  02111-1307, USA.            *
 ***************************************************************************/
#include “evaconnecter.h”
#include “evahtmlparser.h”
#include “evanetwork.h”
#include “evapacketmanager.h”
#include “evaresource.h”
#include “evasetting.h”
#include “evasocket.h”
#include “evauser.h”
#include “evausersetting.h”
#include “evaservers.h”
#include “qmdcodec.h”
#include “evaqtutil.h”
#include “evapicmanager.h”
#include “evauhmanager.h”
#include “regiongrabber.h”
#include “filetrans/evafilemanager.h”

封了这么多类,c++,就是包来报去,一个文件里面,没啥具体的实现,包了底层,加了几个函数,浪费这么多代码行。

/***************************************************************************
 *  Copyright (C) 2004 by yunfan                                          *
 *  yunfan_zg@163.com                                                    *
 *                                                                        *
 *  This program is free software; you can redistribute it and/or modify  *
 *  it under the terms of the GNU General Public License as published by  *
 *  the Free Software Foundation; either version 2 of the License, or    *
 *  (at your option) any later version.                                  *
 *                                                                        *
 *  This program is distributed in the hope that it will be useful,      *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
 *  GNU General Public License for more details.                          *
 *                                                                        *
 *  You should have received a copy of the GNU General Public License    *
 *  along with this program; if not, write to the                        *
 *  Free Software Foundation, Inc.,                                      *
 *  59 Temple Place – Suite 330, Boston, MA  02111-1307, USA.            *
 ***************************************************************************/
#ifndef EVARESOURCE_H
#define EVARESOURCE_H
#include <qobject.h>
#include <qfile.h>
#include <qmap.h>
#include <qpixmap.h>
#include <qimage.h>
#include <qmovie.h>  //这个movie播放gif的。。。
#include <qsize.h>
#ifndef MaxFaceNumber  //最大  脸,头像? 数目
#define MaxFaceNumber 101
#endif
class EvaSetting;
class EvaServers;
class QHttp;  //这里又来个http
class EvaImageResource : public QObject
{
    Q_OBJECT
public:
    EvaImageResource();
    ~EvaImageResource();
                   
                   
    const QString getFacePath() const;
    const QString getIconPath() ;
    const QString getSmileyPath() const;
    const QString getQQShowPath() const;
                   
    const int getFaceID(const int fileIndex) const ;
    const int getFaceFileIndex(const int faceId);
    QPixmap *getFace(const int fileIndex, const bool on = true);
    QPixmap *getIcon(QString name);
    const QString getIconFullPath(QString name);
    const QMovie *getSmiley(const int fileIndex);  //gif的动画
                   
    const QMovie *getLoginMovie();
                   
    const bool loadImage();
    const QString &getImageRootPath() const { return imageRoot; }
    void setImageRootPath( QString &path) { imageRoot = path; }
                   
    const QString getThemePath() const { return themePath; }
    void setThemePath( const QString &path) { themePath = path; }
    QPixmap *getQQShow(const int id);
    void setUserHeadImage(QMap<int, QImage> imageOnList, QMap<int, QImage> imageOffList);
    void addUserHeadImage(const int id, QImage imgOn, QImage imgOff);
    QPixmap *getUserHeadPixmap(const int id, bool isGrayscale = false);
signals:
    void qqShowReady(const int);
public slots: 
    void requestQQShow(const int id); 
private:
    bool loadFace();
    bool loadIcon();
    bool loadSmiley();
    QMap<QString, QPixmap> faceList;
    QMap<QString, QPixmap> iconList;
    QMap<QString, QString> iconFileNameMap;
    QMap<QString, QMovie> smileyList;
    QMap<int, QPixmap> imgOnList;
    QMap<int, QPixmap> imgOffList;
    QMovie loginMng;
    int faceId[MaxFaceNumber];  // store faceID, index is the fileID
    QString imageRoot;
    QString themePath;
                   
    bool isDownloadingQQShow;
    int downloadID;
    QFile qqshowFile;
    QString qqshowFilename;
    QHttp *http;
                   
private slots:
    void slotQQShowDone(bool error);
};
//又是声音,又是图像,不错。
class EvaSoundResource
{
public:
    EvaSoundResource();
    ~EvaSoundResource(){}
    //const bool loadSound(){ return false; }
    void playNewMessage();
    void playSysMessage();
    void playOnlineSound();
    void setSoundDir(const QString &path) { soundRoot = path; }
    const QString &getSoundDir() const { return soundRoot; }
private:
    void playSound(const QString &filename);
    QString soundRoot;
};
//把所有的资源,初始化
class EvaGlobal
{
public:
    EvaGlobal();
    virtual ~EvaGlobal();
                   
    static QString &getDirPath();
    const bool loadImage();
    //const bool loadSound();
    const bool loadEvaSetting();
                   
    EvaImageResource *getImageResource() { return imgResource;}
    EvaSoundResource *getSoundResource() { return sndResource;}
    EvaSetting *getEvaSetting() { return system; }
    EvaServers *getEvaServers() { return servers; }
                   
    const QSize &getFaceSize() const { return faceSize; }
    void setFaceSize( const QSize size) { faceSize = size; }
private:
    void initialize();
    void initImage();
    void initSound();
    void initEvaSetting();
    void initServers();
                   
    static QString dirPath;
    EvaSetting *system;
    EvaServers *servers;
    EvaImageResource *imgResource;
    EvaSoundResource *sndResource;
    QSize faceSize;
};
#endif

 

/***************************************************************************
* Copyright (C) 2004 by yunfan *
* yunfan_zg@163.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place – Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include “evaresource.h”
#include “evasetting.h”
#include “evaservers.h”

#include <stdlib.h>
#include <qapplication.h>
#include <qhttp.h>
#include <qdir.h>
#include <qfileinfo.h>
#include <qdatastream.h>
#include <kaudioplayer.h> //哦。这里又用的谁的库?k开头kDE?
#include <kglobal.h>
#include <kstandarddirs.h>

EvaImageResource::EvaImageResource()
{
//imageRoot = qApp->applicationDirPath() + “/images”;
themePath = “”;
imageRoot = EvaGlobal::getDirPath() + “/image”;
isDownloadingQQShow = false;
http = new QHttp();
connect ( http, SIGNAL(done(bool)), SLOT(slotQQShowDone(bool))); //done什么了?
}

EvaImageResource::~EvaImageResource()
{
}

const QString EvaImageResource::getFacePath() const
{
return imageRoot + “/face”;
}

const QString EvaImageResource::getIconPath()
{
if(themePath == “” )
themePath = imageRoot + “/theme”;
return themePath;
}

const QString EvaImageResource::getSmileyPath() const
{
return imageRoot + “/smiley”;
}

const int EvaImageResource::getFaceID(const int fileIndex) const
{
if(fileIndex<=0 || fileIndex> MaxFaceNumber)
return faceId[0];
return faceId[fileIndex-1];
}

const int EvaImageResource::getFaceFileIndex(const int faceId)
{
int index = (faceId<0)?1:faceId/3 + 1;
if(index<0 || index>101) index = 101;
return index;
}

QPixmap *EvaImageResource::getFace(const int fileIndex, const bool on)
{
QString key = QString::number((fileIndex>0)?fileIndex:1);
if(!on) key+=”off”;
QMap<QString, QPixmap>::Iterator iter = faceList.find(key);
if(iter== faceList.end()) return NULL;
return &(iter.data());
}

QPixmap *EvaImageResource::getIcon(QString name)
{
QMap<QString, QPixmap>::Iterator iter = iconList.find(name);
if(iter== iconList.end()) return NULL;
return &(iter.data());
}

const QString EvaImageResource::getIconFullPath(QString name)
{
QMap<QString, QString>::Iterator iter = iconFileNameMap.find(name);
if(iter== iconFileNameMap.end()) return “”;
return getIconPath() + “/” + iter.data();
}

const QMovie *EvaImageResource::getSmiley(const int fileIndex)
{
QString key = QString::number(fileIndex);
QMap<QString, QMovie>::Iterator iter = smileyList.find(key);
if(iter== smileyList.end()) return NULL;
return &(iter.data());
}

const QMovie *EvaImageResource::getLoginMovie()
{
return &loginMng;
}

const bool EvaImageResource::loadImage()
{
return (loadFace() && loadIcon() && loadSmiley());
}

bool EvaImageResource::loadFace()
{
QString path = getFacePath();
QFile file( path + “/face.theme”);
if(!file.open(IO_ReadOnly)){
return false;
}

QTextStream stream(&file);
QString line, imagePath;
QStringList lineList;
while(!stream.atEnd()){
line = stream.readLine().stripWhiteSpace();

lineList = QStringList::split(“:”, line);
if(lineList.size() != 2)
continue;

lineList[0].stripWhiteSpace();
imagePath = path + “/” + lineList[1].stripWhiteSpace();
QPixmap img(imagePath);
if(!img.isNull())
faceList[lineList[0]] = img;
}

file.close();

for(int i = 0; i < MaxFaceNumber ; i++) {
faceId[i] = i * 3 + 1;
}
return true;
}

bool EvaImageResource::loadIcon()
{
QString path = getIconPath() + “/eva.theme”;
QDir d;
if(!d.exists(path)){
themePath = “”; // if theme not exist, load default one
path = getIconPath() + “/eva.theme”;
}
QFile file( path);
if(!file.open(IO_ReadOnly)){
return false;
}

QTextStream stream(&file);
QString line, imagePath;
QStringList lineList;

while(!stream.atEnd()){
line = stream.readLine().stripWhiteSpace();

lineList = QStringList::split(“:”, line);

if(lineList.size() != 2)
continue;

lineList[0].stripWhiteSpace();
imagePath = getIconPath() + “/” + lineList[1].stripWhiteSpace();
if(lineList[0] == “LOGIN_MNG”){
loginMng = QMovie(imagePath);
continue;
}
QPixmap img(imagePath);
if(!img.isNull()){
iconList[lineList[0]] = img;
iconFileNameMap[lineList[0]] = lineList[1].stripWhiteSpace();
}
}

file.close();
return true;
}

bool EvaImageResource::loadSmiley()
{
QString path = getSmileyPath();
QFile file( path + “/smiley.theme”);
if(!file.open(IO_ReadOnly)){
return false;
}

QTextStream stream(&file);
QString line, imagePath;
QStringList lineList;

while(!stream.atEnd()){
line = stream.readLine().stripWhiteSpace();

lineList = QStringList::split(“:”, line);

if(lineList.size() != 2)
continue;

lineList[0].stripWhiteSpace();
imagePath = path + “/” + lineList[1].stripWhiteSpace();
QMovie m(imagePath);
if(!m.isNull())
smileyList[lineList[0]] = m;
}

file.close();
return true;
}

const QString EvaImageResource::getQQShowPath() const
{
QString evaHome = QDir::homeDirPath() + “/.eva”;//隐藏文件。
QDir d;
if(!d.exists(evaHome)){
return “”;
}
if(!d.cd(evaHome)) return “”;
if(!d.exists(“QQShow”)){
if(!d.mkdir(“QQShow”, false))return “”;
}
return evaHome + “/QQShow”;
}

QPixmap *EvaImageResource::getQQShow(const int id)
{
QString path = getQQShowPath() +”/”+ QString::number(id) + “.gif”;
QDir d;
if(d.exists(path))
return new QPixmap(path);
return NULL;
}

void EvaImageResource::requestQQShow(const int id)
{
if(isDownloadingQQShow) return;
QString path = getQQShowPath();
if(path == “”) return;

qqshowFile.setName(path +”/”+ QString::number(id) + “.gif” );
if(qqshowFile.exists()){
qqshowFile.remove();
}

if ( !qqshowFile.open( IO_WriteOnly ) ) {
printf(“cannot create the image\n”);
return;
}
http->setHost( “qqshow-user.tencent.com” ); //哦,从网站下载下来的。这个网址,连接,永远不变吗?
int picNum = rand()*100;
QString remoteFile = “/”+QString::number(id) + “/10/00/” + QString::number(picNum) +”.gif”;
downloadID = id;
http->get( remoteFile, &qqshowFile );
}

void EvaImageResource::slotQQShowDone( bool error )
{
qqshowFile.close();
if(error){
printf(“download error: %d\n”,error);
isDownloadingQQShow = false;
return;
}
isDownloadingQQShow = false;
emit qqShowReady(downloadID);
}

void EvaImageResource::setUserHeadImage(QMap<int, QImage> imageOnList, QMap<int, QImage> imageOffList)
{
QMap<int, QImage>::Iterator it = imageOnList.begin();
while(it != imageOnList.end()){
imgOnList[it.key()] = QPixmap(it.data());
++it;
}
it = imageOffList.begin();
while(it != imageOffList.end()){
imgOffList[it.key()] = QPixmap(it.data());
++it;
}
}

QPixmap *EvaImageResource::getUserHeadPixmap(const int id, bool isGrayscale)
{
QPixmap * result;
QMap<int, QPixmap>::Iterator it;
if(isGrayscale){
it = imgOffList.find(id);
if(it == imgOffList.end())
result = NULL;
else
result = &(it.data());
}else{
it = imgOnList.find(id);
if(it == imgOnList.end()){
result = NULL;
}else
result = &(it.data());
}
return result;
}

void EvaImageResource::addUserHeadImage(const int id, QImage imgOn, QImage imgOff)
{
imgOnList[id] = QPixmap(imgOn);
imgOffList[id] = QPixmap(imgOff);
}

/* ———————————————————————————————- */

EvaSoundResource::EvaSoundResource()
{
soundRoot = EvaGlobal::getDirPath() + “/sound”;
}

void EvaSoundResource::playNewMessage()
{
playSound(“msg.wav”);
}

void EvaSoundResource::playSysMessage()
{
playSound(“system.wav”);
}

void EvaSoundResource::playOnlineSound()
{
playSound(“online.wav”);
}

void EvaSoundResource::playSound(const QString &filename)
{
QString absPath = soundRoot + “/” + filename;
QDir d;
if(!d.exists(absPath)){
absPath = EvaGlobal::getDirPath() + “/sound” + “/” + filename;
}

if(!d.exists(absPath))return;

KAudioPlayer snd(absPath);
snd.play();
}

/* ———————————————————————————————- */

QString EvaGlobal::dirPath = “~/eva”;

EvaGlobal::EvaGlobal()
{
initialize();
}

EvaGlobal::~EvaGlobal()
{
delete imgResource;
delete sndResource;
delete system;
delete servers;
}

QString &EvaGlobal::getDirPath()
{
return dirPath;
}

const bool EvaGlobal::loadImage()
{
if(!imgResource) return false;
return imgResource->loadImage();
}
/*
const bool EvaGlobal::loadSound()
{
if(!sndResource) return false;
return sndResource->loadSound();
}*/

const bool EvaGlobal::loadEvaSetting()
{
if(!system) return false;
return system->loadSetting();
}

void EvaGlobal::initialize()
{
dirPath = KGlobal::dirs()->findResource(“data”, QString::fromLatin1(“eva/servers”));
// QStringList dirs = KGlobal::dirs()->findDirs(“data”, QString::fromLatin1(“eva”));
// for(uint i=0; i<dirs.size(); i++){
// //printf(“dir %i:%s\n”, i, dirs[i].ascii());
// //dirPath = dirs[0];
// break;
// }
if(dirPath == QString::null){
QFileInfo fi;
fi.setFile(QString(getenv(“_”)));
dirPath = fi.dirPath(true);
}else
dirPath = dirPath.left(dirPath.length() – strlen(“/servers”));
//printf(“found data path: %s\n”, dirPath.ascii());
initImage();
initSound();
initEvaSetting();
initServers();
}

void EvaGlobal::initImage()
{
imgResource = new EvaImageResource();
}

void EvaGlobal::initSound()
{
sndResource = new EvaSoundResource();
}

void EvaGlobal::initEvaSetting()
{
system = new EvaSetting();
}

void EvaGlobal::initServers( )
{
servers = new EvaServers(dirPath);
}

还是只是调用一堆接口的文件。

赞(0) 打赏
转载请注明出处:服务器评测 » Linux下仿QQ–eva0.4.1源码研究
分享到: 更多 (0)

听说打赏我的人,都进福布斯排行榜啦!

支付宝扫一扫打赏

微信扫一扫打赏