可可熊D窝

Keep it simple, stupid


  • 首页

  • 关于

  • 标签182

  • 分类8

  • 归档359

  • 搜索

libevent学习-(I)

发表 2009-02-23 | 分类 编程相关 | 评论数:
| 字数: 4k | 阅读 ≈ 4 分钟
[libevent](http://monkey.org/~provos/libevent/)是一个异步事件处理软件函式库,以BSD许可证释出。> 

libevent提供了一组应用程序编程接口(API),让程式设计师可以设定某些事件发生时所执行的函式,也就是说,libevent可以用来取代网络服务器所使用的循环检查架构。

摘自维基百科

http://blog.gslin.info/2005/11/network-programming-using-libevent-i.html
这里介绍了libevent相关的网络编程背景,需要带套访问哦。

以下分析针对libevent-1.4.3-stable。

来看libevent自带的例子:

/*
 * Compile with:
 * cc -I/usr/local/include -o event-test event-test.c -L/usr/local/lib -levent
 */

static void
fifo_read(int fd, short event, void *arg)
{
    char buf[255];
    int len;
    struct event *ev = arg;

    /* Reschedule this event */
    event_add(ev, NULL);

    fprintf(stderr, "fifo_read called with fd: %d, event: %d, arg: %pn",
        fd, event, arg);
    len = read(fd, buf, sizeof(buf) - 1);

    if (len == -1) {
        perror("read");
        return;
    } else if (len == 0) {
        fprintf(stderr, "Connection closedn");
        return;
    }

    buf[len] = '�';
    fprintf(stdout, "Read: %sn", buf);
}

int
main (int argc, char **argv)
{
    struct event evfifo;
    struct stat st;
    const char *fifo = "event.fifo";
    int socket;

    if (lstat (fifo, &st) == 0) {
        if ((st.st_mode & S_IFMT) == S_IFREG) {
            errno = EEXIST;
            perror("lstat");
            exit (1);
        }
    }

    unlink (fifo);
    if (mkfifo (fifo, 0600) == -1) {
        perror("mkfifo");<code></code>
        exit (1);
    }

    /* Linux pipes are broken, we need O_RDWR instead of O_RDONLY */
    socket = open (fifo, O_RDWR | O_NONBLOCK, 0);

    if (socket == -1) {
        perror("open");
        exit (1);
    }

    fprintf(stderr, "Write data to %sn", fifo);
    /* Initalize the event library */
    event_init();

    /* Initalize one event */
    event_set(&evfifo, socket, EV_READ, fifo_read, &evfifo);

    /* Add it to the active events, without a timeout */
    event_add(&evfifo, NULL);

    event_dispatch();
    return (0);
}
[/c]

我把原来代码中WIN平台相关的去掉了,看起来方便一些,这个例子创建了一个pipe,并且使用libevent来监听是否可读,读有数据可读时调用函数fifo_read。
libevent调用比较简单,首先event_init()对event库进行初始化,然后使用event_set()来对某个fd的操作进行监听,接着使用event_add()把这个event激活,这里可以指定超时的时间,最后一步event_dispatch(),开始进行循环。

event_init()里只是对外的一个接口,这个函数调用了event_base_new(),分配了一个event_base类型的空间,设置了一些全局变量,使用detect_monotonic来检测是否支持CLOCK_MONOTONIC类型的时钟,这里不太理解为什么要使用clock_gettime(CLOCK_MONOTONIC, &ts)来获得当前时间,这个与gettimeofday得到的精度是一样的,只是一个是标准的时间(UNIX元年算起),一个是开机时间算起,有什么差别吗?

[ CLOCK_MONOTONICI测试代码:](#)

/* gcc -o ftime  ftime.c*/ 
#include<stdio .h>
#include<time .h>
#include<sys /time.h>

int main(void)
{
    struct timeval tp;

    gettimeofday(&tp,NULL);
    printf("sec=%ld\n",tp.tv_sec);

    struct timespec ts;

    clock_gettime(CLOCK_MONOTONIC,&ts);
    printf("sec=%ld\n",ts.tv_sec);
    return 0;
}

结果:

[cocobear@cocobear libevent-1.4.3-stable]$ gcc ftime.c -lrt> 
[cocobear@cocobear libevent-1.4.3-stable]$ ./a.out > 
sec=1235372220> 
sec=4621

接下来就检测可使用的事件检测函数,这里与系统相关的调用被封装成了一个结构eventop:

struct eventop {
    const char *name;
    void *(*init)(struct event_base *);
    int (*add)(void *, struct event *);
    int (*del)(void *, struct event *);
    int (*dispatch)(struct event_base *, void *, struct timeval *);
    void (*dealloc)(struct event_base *, void *);
    /* set if we need to reinitialize the event base */
    int need_reinit;
};

编译时libevent会通过

#ifdef HAVE_SELECT
    &selectops,
#endif

来“动态”的确定eventops数组,在定义这个eventops数组时确定了使用这些事件驱动模型的顺序,如果你机子上有多种可用的模式,则可以通过修改改数组来自定义使用的模型。

在event_base_new()的最后调用了event_base_priority_init()初始化了消息的优先级队列。主要就是对activequeues变量进行空间分配。默认是分配了一个event_list给activequeues。

Comments

山客: monotonic和标准时间在实际使用的差别是,标准时间会correct,从而可能造成定时器问题

duşakabin: Thanks for this fantastic post, I am glad I found this site on yahoo.

PyFetion更新

发表 2009-02-20 | 分类 编程相关 | 评论数:
| 字数: 4.1k | 阅读 ≈ 4 分钟

详细的更新请到google code 查看。

  1. get_info()函数参数处理who遗失的情况;
  2. 向服务器以HTTP方式提交密码时使用urllib.quote()编码;
  3. 修改send_msg()函数;
  4. 清理代码中直接退出的exit函数;
  5. 重写__tcp_recv()函数,以前这里有可能会丢失数据,比如好友列表过长;
  6. 增加隐身登录功能,login(True)表示隐身登录。

以前还有人提到增加隐身登录,我看了下08 PC版的飞信,只能是先登录,然后再设置隐身模式,这样的话增加设置隐身模式就没必要了。

至于登出飞信更是没必要了。

09.02.23 Update:

  1. 上次的代码get_uri被我改出错了,修正了一下;
  2. 修改了使用手机号直接发送的方式,因为目前可以使用tel: 13888888888的方式发送短信,不用从联系人中一个一个找了;不过以前似乎这种方式不行;
  3. 修正了获取联系人信息的XML数据,可以完整的获取联系人;

    Comments

hawkli: nav.fetion.com.cn不能访问了,唉是不是被封了啊,还有什么办法么?

cocobear: 呵呵,希望能有更多利用飞信的好东东.

jifenghy: 非常谢可可熊,用了你的pyfetion,写了一个简单的应用,每天早上7点天气预报短信到我的手机上,部署到了GAE上。 代码放到了http://code.google.com/p/weathermobile/ 谢谢你!

可可熊: To:xinqianli 2.6版本的我没有试过,但是2.6如果用这种方式很容易卡在那里。 没有仔细去研究到底是什么原因,先记一下,有机会再瞧瞧。 多谢了。

可可熊: 我已经算过长度了,在recv里面使用了size,这个参数可以不加,我似乎做得有些画蛇添足。 这一块似乎不太稳定,因为飞信服务器有时候返回好友列表的时候中间会隔不短的一段时间,弄的我很郁闷。在Windows下你可以先把这个参数去掉。

K.T.S: windows下 _tcp_recv方法里如果socket超时,raise PyFetionSocketError(e.read())报错,socket.timeout似乎没有read方法

可可熊: To:volans http://code.google.com/p/pytool/source/detail?r=22 已经更新。 请查看398+ 多谢反馈。

Kermit Mei: $ ./PyFetion.py 12345 corrent your mobile NO. and password 上面的提示中corrent是什么意思?这个怎么用?给个范例萨。 BTW:我没有用过飞信,这个发短信要钱不?

small: 不错,鼓励可可熊,坚持更新

volans: 已经移植了你的代码到GAE上,目前只实现了发短信。 http://gaefetion.appspot.com/

volans: 有的人没有使用飞信业务,但他同意你加他为你的飞信好友了,这些人在你的列表里只有手机号,而没有飞信号码。用官方的飞信软件的好友类表里是有这些人的,图标是绿色(而申请了飞信业务,有飞信号码的好友是灰色) 不知道这样描述你是否明白,或者你看看你的好友列表。

Jove: hehe, 好像只要在实例化PyFetion时,选HTTP登录方式就可以在GAE上用了. 这下我可以给朋友发短信提醒了

Jove: volans, 能共享一下你在GAE上的移植么. 好像GAE里不能使用socket包,所以错误信息如下 File “/base/data/home/apps/aa/1.331593899342273539/main.py”, line 41, in get phone.login() File “/base/data/home/apps/aa/1.331593899342273539/PyFetion.py”, line 88, in login self.register(self.ssic,self.domain) File “/base/data/home/apps/aa/1.331593899342273539/PyFetion.py”, line 204, in register response = self.SIPC.send() File “/base/data/home/apps/aa/1.331593899342273539/PyFetion.py”, line 315, in send self.tcp_init() File “/base/data/home/apps/aa/1.331593899342273539/PyFetion.py”, line 424, in tcp_init self.sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) AttributeError: ‘module’ object has no attribute ‘socket’

可可熊: 没有飞信号码的好友? 我不太理解,飞信好友中还有没有飞信号码的好友吗?

可可熊: To:Jove GAE上应该不能直接使用底层的socket,所以只能使用HTTP的方式;HTTP方式速度有点慢,传输的数据多一些,如果你有DH主机的话直接在上面用Python很方便。

草儿: 没想到你还在继续更新着,我还以为你都停下了呢。

nemo: 挺不错呢~

iefan: 只是如何保持一直在线状态呢?总不能每次发短信都得登录一下吧

volans: Jove,如你所说,改成http方式就可以了,没做过多别的修改。

volans: 可可熊:为什么获得好友列表只能获得飞信用户呢?没有飞信号码的那些好友将不能返回……

可可熊: To:iefan 一直保持在线我没考虑,因为没打算发大量的短信,如果要发很多短信,建议使用定时短信。 至于实现保持在线,只是定时发一发keepalive消息。

可可熊: To: Mei 我不理解你为什么要在命令行后加参数,我给出的例子里面就不是那样写的啊。

xinqianli: 在windows下面,用Python 2.6, 原代码中 data = self.sock.recv(size,socket.MSG_WAITALL) 这一行应该用下列代码替换,否则会报告no attribute ‘MSG_WAITALL’错误。 buffer=”” while len(buffer)<size: data = self.sock.recv(size-len(buffer)) if not data: break buffer+=data

xinqianli: To 可可熊 我对python不熟悉,只是对fetion有点兴趣,学习了一下你的代码 ^_^ 可能你主要在unix-like平台测试的,windows下面socket不支持MSG_WAITALL选项,似乎python库也没有考虑提供封装,因此要根据消息长度自己算len吧

帆船书会: 恩,对,ptfetion似乎不能用了啊。

damon: 昨天晚上成功测试发送! 马上就停电了 郁闷

xiangking: 学习! 什么时候把这个修改成能在智能手机上使用就好了

damon: 125.69.45.214 - - [24/Apr/2009:20:38:44 -0700] “GET / HTTP/1.1” 500 0 - “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; TheWorld),gzip(gfe)”E 04-24 08:38PM 44.702 : Traceback (most recent call last): File “/base/data/home/apps/djybbs/1.333029036534336496/PyFetion.py”, line 642, in main() File “/base/data/home/apps/djybbs/1.333029036534336496/PyFetion.py”, line 639, in main time.sleep(Timeout2);

Eric: 你好,我在linux下使用PyFetion有问题,短信发送不出去,在windows下能发送出去,然后我看到代码上有这个配置: 是不是platform需要修改为linux下的,还是其他的原因呢。谢谢!

Eric: platform=”W5.1” 这个是否说明运行平台是在windows下,如果我是在linux下又该如何修改呢?

可可熊: Linux下使用没有问题,代码是跨平台的。

Eric: 不需要修改什么吗,我现在就是遇到这个问题了,windows下能发送,linux就不能发送了。你的意思代码完全不需要修改吗?

cocobear: 你遇到问题,你要说明是什么样的,给出具体的描述,不然别人没办法了解你的情况。

Eric: 谢谢你的提醒,我现在测试又通过了,问题不在代码上。再请教一个问题呢,那些关于飞信的XML,有参考资料吗。

可可熊: XML相关的资料很多的,这是标准格式,你看相关的文档就行了。

Leo Jay: 刚才下载了你最新的r41的代码,好像里面有tab和space混用的情况。

Eric: 你好,我又来了,我想问个问题就是我现在有个应用,就是想通过指定端口来发送短信,不知道这个是不是直接在电话号码后面跟上端口号就行了呢?

Terry: 我也在GAE上搭建了一个https://fetionlib.appspot.com/ 可以群发、定时发送、加好友和程序调用等。

libev编译篇

发表 2009-02-07 | 分类 编程相关 | 评论数:
| 字数: 1.5k | 阅读 ≈ 1 分钟

先给出libev的主页http://software.schmorp.de/pkg/libev.html,libev是一个高性能的事件驱动模型,与libevent类似,不过设计更为小巧,简洁。

libevent有成功的应用–memcached,libev是一个比较新的项目,代码比较少,所以这几天来研究下这个。

首先从CVS中下载最新的代码:

cvs -z3 -d :pserver:anonymous@cvs.schmorp.de/schmorpforge co libev

CVS代码中有autogen.sh文件,执行该文件会生成configure,我机子上出了点问题,需要首先运行
automake –add-missing
然后就是./configure && make && make install 了。
安装好后会有一个提示:
Libraries have been installed in:>
/usr/local/lib>

If you ever happen to want to link against installed libraries> 
in a given directory, LIBDIR, you must either use libtool, and> 
specify the full pathname of the library, or use the `-LLIBDIR'> 
flag during linking and do at least one of the following:> 
   - add LIBDIR to the `LD_LIBRARY_PATH' environment variable> 
     during execution> 
   - add LIBDIR to the `LD_RUN_PATH' environment variable> 
     during linking> 
   - use the `-Wl,--rpath -Wl,LIBDIR' linker flag> 
   - have your system administrator add LIBDIR to `/etc/ld.so.conf'> 

See any operating system documentation about shared libraries for> 
more information, such as the ld(1) and ld.so(8) manual pages.

需要注意一下,因为默认这个库安装在了/usr/local/lib/里,所以运行程序时有可能会提示找不到libev.so这个动态库。我们需要在编译时加上-LLIBDIR参数,然后设置LD_RUN_PATH这个环境变量。

安装好为了测试libev,可以使用lighttz,其实我是从这里知道的libev,下载C文件,使用下面的命令来编译:

LD_RUN_PATH=/usr/local/lib/> 
export LD_RUN_PATH> 
gcc -LLIBDIR -o lighttz lighttz.c -lev

高效的使用bash

发表 2009-02-06 | 分类 Linux | 评论数:
| 字数: 782 | 阅读 ≈ 1 分钟

以前在用bash的时候觉得TAB补齐如果能做得更智能一些就好了,比如我使用evince ,bash就会自动列出目录下所有的pdf文件,我还想着自己动修改bash来实现,不过偶然发现了bash-completion这个东西,它不仅可以实现上面的功能,而且还可以补全sudo,补全命令的参数,下面这个图可以很好的代表bash-completion
bash-completion
http://www.caliban.org/bash/

Comments

kermit.mei: Hi,怎么把自己写的程序的选项加入到只能提示里? 那个主页好像没有说,也可能是我对英语不够敏感没找到。

Amankwah: 额的神啊~ bash-completion~ Ubuntu从我用的时候就有的了,我都以为是标配呢~结果今天是新闻~

cocobear: 额的天呢,老大来这里看新闻啊!!

可可熊: zsh我试了试不可以补齐参数,智能识别后缀倒是可以,不过似乎用着不太爽。纠错不太理解怎么用。

麦克狼: 您好,看来您的关于SDL的文章之后,想向您请教有关Linux下SDL开发的问题。请问您有QQ或者电话什么的吗,如果方便请告诉我。我的邮箱是44222853@163.com。我毕业论文是这方面的,有很多疑问。谢谢!!

luguo: 可以的,看下面: % ls - -1 – single column output --all -a – list entries starting with . --almost-all -A – list all except . and .. [snip]

luguo: 如果我没记错的话,zsh一直都可以。。。。而且zsh还可以纠错~~

c: To Amankwah: 怎么会是标配呢?额是第一次听说~

可可熊: 说明你太笨了!

wind: 事实上我没看明白这张图和你说的关系

出来发个牢骚

发表 2009-02-04 | 分类 Life | 评论数:
| 字数: 1.7k | 阅读 ≈ 2 分钟
Reply from 192.168.1.1: bytes=32 time=24ms TTL=64> 
Reply from 192.168.1.1: bytes=32 time=94ms TTL=64> 
Reply from 192.168.1.1: bytes=32 time=117ms TTL=64> 
Reply from 192.168.1.1: bytes=32 time=100ms TTL=64> 
Reply from 192.168.1.1: bytes=32 time&lt;1ms TTL=64> 
Reply from 192.168.1.1: bytes=32 time&lt;1ms TTL=64> 
Reply from 192.168.1.1: bytes=32 time&lt;1ms TTL=64> 
Reply from 192.168.1.1: bytes=32 time&lt;1ms TTL=64> 
Reply from 192.168.1.1: bytes=32 time&lt;1ms TTL=64> 
Reply from 192.168.1.1: bytes=32 time&lt;1ms TTL=64> 
Reply from 192.168.1.1: bytes=32 time=1ms TTL=64> 
Reply from 192.168.1.1: bytes=32 time&lt;1ms TTL=64> 
Reply from 192.168.1.1: bytes=32 time=106ms TTL=64> 
Reply from 192.168.1.1: bytes=32 time=176ms TTL=64> 
Reply from 192.168.1.1: bytes=32 time=35ms TTL=64> 
Reply from 192.168.1.1: bytes=32 time&lt;1ms TTL=64> 
Reply from 192.168.1.1: bytes=32 time=2ms TTL=64> 
Reply from 192.168.1.1: bytes=32 time=31ms TTL=64> 
Request timed out.> 
Reply from 192.168.1.1: bytes=32 time=43ms TTL=64> 
Reply from 192.168.1.1: bytes=32 time=26ms TTL=64> 
Reply from 192.168.1.1: bytes=32 time&lt;1ms TTL=64> 
Reply from 192.168.1.1: bytes=32 time&lt;1ms TTL=64

ping路由时通时不通,而且延时很大,交换机上灯闪得也很慢,而别人的灯闪得很快,而且一致。
看个网页还能凑合着打开,要是玩个即时通信的游戏非得卡死,VS中延时好几百ms。

同样是一个交路机出来的,别人网络没有任何问题,我这里确这样,连电脑的线也换了好几根,也都一样,看来只能是网卡的问题了,有时间去买个网卡。

可惜我这里有好几个有线的交换机,不然现在弄无线网络现在挺方便,而且也相当便宜,一个无线路由80多块钱,无线网卡30多块钱,觉得比拉网线划算多了。

Comments

Amankwah: 弄个仪器测试一下么~好歹咱们是网络工程专业啊,兄弟。

可可熊: 太浪费了,有两个有线的,再买,这么多放着吃啊!

luguo: 俺一回来就无线了,整天拽着根网线确实不爽啊~~!

草儿: 你没检查你房间布的暗线?要不你就自己出钱买个无线路由器得了。

NONENONE: 感觉是网线的问题, 我家以前也是这样, PING ISP的GW这样, 最后发现墙上的插座质量不对, 还一下就好了

1…141516…72
cocobear

cocobear

爱折腾的技术宅一枚

359 日志
8 分类
182 标签
RSS
GitHub E-Mail Twitter 豆瓣
友情链接
  • 王聪
  • 老大
0%
© 2007 – 2020 cocobear | 521k | 7:54
由 Hexo 强力驱动 v3.9.0
|
主题 – NexT.Gemini v6.7.0
Hosted by GitHub Pages