Category: C/C++

  • Protobuf Demo

    操作系统:Fedora core 16

    下载安装

    Go to http://code.google.com/p/protobuf/ download the latest updates version

    $ wget http://protobuf.googlecode.com/files/protobuf-2.4.1.tar.bz2
    $ tar xvf protobuf-2.4.1.tar.bz2
    $ cd protobuf-2.4.1/
    $ ./configure && make && sudo make install

    一般默认安装在/usr/local 目录下,需要导入环境变量:

    编辑 ~/.bashrc 在后面添加:

    export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
    export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig$PKG_CONFIG_PATH

    编译jar包:

    $ cd protobuf-2.4.1/
    $ sudo yum install maven
    $ mvn package

    在 target/ 目下下生成 protobuf-java-2.4.1.jar, 使用的时候,导入环境变量CLASSPATH 就行了。

    Ubuntu 11.10,安装也很简单:

    $ sudo apt-get install libprotobuf-dev libprotobuf-java
    $ export CLASSPATH=$CLASSPACH:/usr/share/java/protobuf.jar

    书写 .proto 文件
    一个比较好的习惯是认真对待 proto 文件的文件名。比如将命名规则定于如下:
    packageName.MessageName.proto

    下载 vim 编辑proto语法亮度插件: http://protobuf.googlecode.com/svn/tags/release-2.0.1/editors/proto.vim 按照里面的说明安装。或者照这个操作,https://github.com/garyharan/vim-proto

    服务器端与客户端socket通讯
    服务器段用C++实现,客户端 Java/C++,具体代码放在 github:https://github.com/lytsing/protobuf-demo 这里就不贴出来了。

    参考: Protocol Buffers的安装使用和C++入门示例

  • A simple http web service

    很久没更新blog了,主要是这段时间工作太忙,刚加入一家创业公司 iboxpay,做移动支付,就是做中国版的Square 🙂

    重新温习 socket之类的内容,翻看以前写的一些代码,整理一下,一个简单的 web server,放在 github:https://github.com/lytsing/myhttpd
    这个例子很简单,但涉及到的内容都具备了:

    • 基础socket使用
    • 多路复用
    • 信号处理
    • 配置文件读取

    等周末再完善,加上ipv6支持,当做一个学习的教程吧。

  • ip地址查询(C++版)

    最近公司服务器被hack,怀疑的ip每次都登录ip138.com查询,很麻烦,想起维护新糊涂的时候,曾经写个小程序统计用户ip地址来源。ip数据库是纯真版,代码是参考别人的,忘了是谁写的,我就只修改了main函数。

    /**
     * file: ip_from.cpp
     * @date: 2007.4.20
     *
     */
    
    #include <cstdio>
    #include <cstdlib>
    #include <string>
    #include <sstream>
    #include <iostream>
    #include <iomanip>
    #include <ios>
    #include <fstream>
    #include <vector>
    #include <iterator>
    #include <stdexcept>
    #include <algorithm>
    using namespace std;
    
    typedef unsigned int IP_TYPE;
    
    const int  IP_SIZE = 4;
    const int  OFFSET_SIZE = 3;
    const int  INDEX_RECORD_SIZE = IP_SIZE + OFFSET_SIZE;
    
    class IpLocater {
    private:
        FILE* dbfile;
        int   first_index;
        int   last_index;
        enum  { REDIRECT_MODE_1 = 0x01, REDIRECT_MODE_2 = 0x02 };
    protected:
    
    public:
        IpLocater(const string dbfilename = "QQWry.Dat")
        {
            dbfile = fopen(dbfilename.c_str(),"rb");
            if (!dbfile) {
                printf("can not open the ip db file %s\n", dbfilename.c_str());
                exit(0);
            }
    
            fread(&first_index, sizeof(int), 1, dbfile);
            fread(&last_index, sizeof(int), 1, dbfile);
        }
        ~IpLocater(){
            fclose(dbfile);
        }
    
        int getRecordCount() const {
            return (last_index - first_index ) / INDEX_RECORD_SIZE + 1;
        }
        
        string readString(const int offset = 0){
            if (offset) {
                fseek(dbfile, offset, SEEK_SET);
            }
    
            char ch = fgetc(dbfile);
            ostringstream sstr ;
            while (ch != 0 && ch != EOF) {
                sstr << ch;
                ch = fgetc(dbfile);
            }
            return sstr.str();
        }
    
        inline int readInt3(const int offset = 0 ) {
            if (offset) {
                fseek(dbfile,offset,SEEK_SET);
            }
        
            int result = 0;
            fread(&result, sizeof(char), 3, dbfile);
            return result;
        }
    
        string readAreaAddr(const int offset = 0) {
            if (offset) {
                fseek(dbfile, offset, SEEK_SET);
            }
            char b = fgetc(dbfile);
            if (b == REDIRECT_MODE_1 || b == REDIRECT_MODE_2) {
                int areaOffset = 0;
                fread(&areaOffset, 1, 3, dbfile);
                if (areaOffset) {
                    return readString(areaOffset);
                } else {
                    return "Unkown";
                }
            } else {
                fseek(dbfile, -1, SEEK_CUR);
                return readString();
            }
        }
    
        unsigned int readLastIp(const int offset) {
            fseek(dbfile, offset, SEEK_SET);
            unsigned int ip = 0;
            fread(&ip, sizeof(unsigned int), 1, dbfile);
            return ip;
        }
    
        string readFullAddr(const int offset, int ip = 0) {
            string address = "";
    
            fseek(dbfile, offset + 4, SEEK_SET);
    
            char ch = fgetc(dbfile);
            if (ch == REDIRECT_MODE_1) {
                int countryOffset = 0;
                fread(&countryOffset,sizeof(char),3,dbfile);
                
                fseek(dbfile, countryOffset, SEEK_SET);
                char byte = fgetc(dbfile);
                if (byte == REDIRECT_MODE_2 ) {
                    int p = 0;
                    fread(&p, 1, 3, dbfile);
                    address = readString(p);
                    fseek(dbfile, countryOffset + 4, SEEK_SET);
                } else {
                    address = readString(countryOffset);
                }
                address += readAreaAddr(); // current position
            } else if (ch == REDIRECT_MODE_2) {
                int p = 0;
                fread(&p, 1, 3, dbfile);
                address = readString(p);
                address += readAreaAddr(offset + 8);
            } else {
                fseek(dbfile, -1, SEEK_CUR);
                address = readString();
                address += readAreaAddr();
            }
    
            return address;
        }
    
        void printAddr(int first = 0, int count = 100){
            int record_count  = getRecordCount();
            for (int i = first; i< first+count && i<record_count; i++)
            {
                fseek(dbfile,i*INDEX_RECORD_SIZE+first_index,SEEK_SET);
                unsigned int ip = 0;
                fread(&ip,sizeof(unsigned int),1,dbfile);
                int offset = 0;
                fread(&offset,1,OFFSET_SIZE,dbfile);
                cout << ip2string(ip) << "-" << ip2string(readLastIp(offset))
                    << readFullAddr(offset) << endl;
            }
        }
    
        int find(unsigned int ip,int left ,int right) {
            if (right - left == 1) {
                return left;
            } else {
                int middle = (left + right) / 2;
                
                int offset = first_index + middle * INDEX_RECORD_SIZE;
                fseek(dbfile,offset,SEEK_SET);
                unsigned int new_ip = 0;
                fread(&new_ip,sizeof(unsigned int),1,dbfile);
                
                if (ip >= new_ip) {
                    return find(ip,middle,right);
                } else {
                    return find(ip,left,middle);
                }
            }
        }
    
        string getIpAddr( unsigned int ip){
            int index = find(ip,0, getRecordCount() - 1 );
            int index_offset = first_index + index * INDEX_RECORD_SIZE + 4;
            int addr_offset = 0;
            fseek(dbfile,index_offset,SEEK_SET);
            fread(&addr_offset,1,3,dbfile);
            string address = readFullAddr( addr_offset,ip );
            return address;
        }
        
        string ip2string( unsigned int ip) const{
            ostringstream sstr;
            sstr << ((ip & 0xff000000)>>24) ;
            sstr << "." << ((ip & 0xff0000)>>16);
            sstr << "." << ((ip & 0xff00)>>8);
            sstr << "." << (ip & 0xff);
            return sstr.str();
        }
    
        unsigned int string2ip(const string ipstr)const{
            string str = ipstr;
            unsigned int ip = 0;
            int p = 0;
            p = str.find(".");
            ip += atoi(str.substr(0,p).c_str());
            ip <<= 8;
            str = str.substr(p+1,str.length());
            p = str.find(".");
            ip += atoi(str.substr(0,p).c_str());
            ip <<= 8;
            str = str.substr(p+1,str.length());
            p = str.find(".");
            ip += atoi(str.substr(0,p).c_str());
            ip <<= 8;
            ip += atoi(str.substr(p+1,str.length()).c_str());
            return ip;
        }
    
        string getIpAddr(string ip){
    
            return getIpAddr( string2ip( ip ) );
        }
    };
    
    int main(int argc, char* argv[])
    {
        IpLocater locater("/var/opt/QQWry.Dat");
    #if 0   
        if (argc > 1) {
            string ip = argv[1];
            cout << locater.getIpAddr(ip) << endl;
        } else {
            string str;
            while (cin >> str) {
                cout << locater.getIpAddr(str) << endl;
            }
        }
    #endif
    
        long counter = 0;
    
        if (argc > 1) {
            string file_name = argv[1];
            ifstream infile(file_name.c_str(), ios::in);
    
            if (!infile) {
                cerr << "oops: unable to open log file"
                    << file_name << '\n';
                return -1;
            }
    
            string tmp;
            vector<string> vect;
    
            try {
                while (getline(infile, tmp, '\n'))
                    vect.push_back(tmp.substr(0, tmp.find(' ')));
            } catch (exception& e) {
                cout << e.what() << '\n';
            }
    
            sort(vect.begin(), vect.end());
            vector<string>::iterator it = unique(vect.begin(), vect.end());
            typedef vector<string>::const_iterator iter;
            streamsize prec = cout.precision();
    
            for (iter i = vect.begin(); i != it; ++i) {
                ++counter;
                cout << setprecision(18) << *i << '\t';
                cout << setprecision(prec) << locater.getIpAddr(*i) << endl;
            }
        } else {
            string str;
            while (cin >> str) {
                cout << locater.getIpAddr(str) << endl;
            }
        }
    
        cout << "Today the web access ip total is: " << counter << endl;
    
        return 0;
    }
    

    编译:
    g++ -Wall -o ip_from ip_from.cpp

    代码写死了,记得ip纯真数据库放在 /var/opt/QQWry.Dat 主要用来分析apache的日志。

    newytht:~/bin$ cat stat_ip_from

    #!/bin/sh
    
    now=`date +"%Y%m%d"`
    log_file="/usr/local/apache2/logs/access_log.$now"
    
    if [ -f $log_file ]; then
    	ipnum=`./ip_from '  < /usr/local/apache2/logs/access_log.$now ;
    	echo "$ipnum"  >> /home/bbs/0Announce/bbslist/ip_stat_from
    fi
  • 用C++写ruby扩展

    为了测试CDMA短信的发送方便,于是想到编译成lib,提供ruby使用。

    SmsObject.h:
    void SendSms(const char* msg, const char* number, char* out);

    main.cpp:

    //
    // by deli 2009.6.11
    //
    #include <ruby.h>
    #include "SmsObject.h"
    
    static VALUE makepdu(VALUE self, VALUE arg1, VALUE arg2) {
        VALUE s;
        char pdu[512] = {0};
        char* msg = RSTRING(arg1)->ptr;
        char* number = RSTRING(arg2)->ptr;
    
        SendSms(msg, number, pdu);
        s = rb_str_new2(pdu);
    
        return s;
    }
    
    extern "C"
    void __declspec(dllexport) Init_sms() {
        VALUE myModule = rb_define_module("CDMA");
    
        VALUE myClass = 
            rb_define_class_under(myModule, "SMS", rb_cObject);
    
        int arg_count = 2;
        rb_define_method(myClass, "makepdu", RUBY_METHOD_FUNC(makepdu), arg_count);
    }

    注意: C++要加上RUBY_METHOD_FUNC, C不用加。不然就会出现类似的错误:
    error C2664: ‘rb_define_method’ : cannot convert parameter 3 from
    ‘unsigned long (unsigned long,unsigned long,unsigned long)’ to ‘unsigned long (_
    _cdecl *)(…)’
    None of the functions with this name in scope match the target type

    test.rb:

    #!/usr/bin/ruby 
    
    require 'sms'
    
    include CDMA
    
    obj = SMS.new
    pdu = obj.makepdu('什么都可以想,什么都可以不想,便觉得是个自由的人', '15338896034')
    
    puts pdu

    D:\Ruby\ruby-serial\sms>ruby test.rb
    0000021002040702c54ce225a8d008420003200000013220c27602724487ea9f7a772b079ff86276
    02724487ea9f7a772a706b079ff8627dfc4e4afcbb317a71540f53a98bb42275d00501a70801c00d
    0101

    大概就是这样。

  • 用vim写c/c++程式的一些设定

    —— Accelerated editing your code!

    前辈们说:“一个人对Linux的熟悉程度,看他对vi的操作就知道了”。Broncho成员们都一直用这个编辑器,听说网易强行使用vim。先进的生产工具代表先进的生产力,让我们来设置一下属于自己的vim.

    首先,弄一个 .vimrc 文件
    一般从 /usr/share/vim/vim72/example_vimrc 拷过来用就差不多了.
    $ cp /usr/share/vim/vim72/example_vimrc ~/.vimrc

    然后主要就是修改配置文件 ~/.vimrc

    “主题,我喜欢这个,一般要设终端是白字黑背景色.
    colo desert

    ” 对齐与缩进
    set cindent
    set smartindent
    set shiftwidth=4
    set ts=4

    ” for cpp class, switch
    set cino=:0g0t0(sus

    ” 设置行号
    set nu

    C/C++ 插件,这些插件都可以在vim官方网www.vim.org下载得到.
    1. c-surpport 写c/c++必备
    http://www.vim.org/scripts/script.php?script_id=213

    ” 设置leader的快捷键,原来的“\”太远了,而且位置还不固定
    ” leader key for c.vim
    let g:C_MapLeader  = ‘,’

    一些文件模板不太符合我的要求,不美观,所以我改为broncho通用的
    cd ~/.vim/c-support/templates
    编辑 c.comments.template
    还有 Templates这个文件,定义很多宏,主要是作者,邮件,版权等等。

    2. snippetsemu 代码片段
    在 Vim 上使用像是 Textmate 的功能
    看过Rails的demo,你一定会对那个编辑器 Textmate 很感兴趣,没错,很简单的。

    svn checkout http://snippetsemu.googlecode.com/svn/trunk/ textmate
    mv textmate/ ~/.vim
    编辑 ~/.vimrc,填上

    filetype on
    filetype plugin on
    set runtimepath+=~/.vim/textmate
    set runtimepath+=~/.vim/textmate/after
    如果装了 supertab.vim,那么Tab会冲突,解决方法:
    在 ~/.vimrc 中加入
    so ~/.vim/plugin/supertab.vim

    3. code_complete
    code_complete很不错,和SuperTab冲突 code_complete 的 tab 键可以改成其他键的,比如我就改为了Ctrl+j,和 latexSuite 一样。

    关于自动补充
    broncho几乎是c写的,所以一般按 Ctrl+p, 按得很happy,90%的都可以自动补充。

    还有很多很多的插件与技巧,工具也不过是工具罢了,一般学会使用20%的功能,就能快速的编辑。