存档

2009年11月 的存档

43个你应当避免的Web设计错误

2009年11月19日 16hot 没有评论

原文链接。 这是一篇关于网站易用性的文章,作者以亲身体会讲述了43条 网站设计中常犯的错误,而无疑这些错误会大大影响网站的可用性。 如今网站易用性已成为一种趋势,但纵观国内的各大网站, 似乎易用性并未成为设计者们广泛理解的概念, 因此希望这篇文章对大家能有作用。

1. 用户必须在几秒钟知道网站是做什么的。注意力是因特网上最有价值的货币。 如果访问者无法在几秒钟之内得知你的网站的方向,他很有可能转而访问其他网站。 你必须迅速地告诉访问者为什么要在你的网站上花费时间。

2. 让网站易于速读。因特网不是书,因此没必要使用大段的文字。 也许我访问你的网站时我正在忙于其他工作,我不得不迅速读完所有内容。 项目符号、标题、副标题、列表,这些都能帮助读者迅速找到他想要的内容。

3. 不要使用难于阅读的花哨字体。当然,某些字体可以让网站精彩纷呈。 不过它们容易阅读吗?如果你的主要目的是传递信息并让读者阅读, 你应该让阅读过程舒服些。

4. 不要用小字体。如上一条所述,你得让读者阅读时感到舒服。 虽然我的Firefox有放大功能,但如果必须放大才能看清一个网站的话, 我就再也不会去访问它了。

5. 不要打开新浏览器窗口。我的第一个网站曾经经常这么做。 原因很简单,在新窗口中打开外部链接,用户就不必离开我的网站。 错!让用户决定如何打开链接,否则浏览器上大大的后退按钮就没必要存在了。 不用担心用户离开你的网站,在必要的时候他们会回来的。

6. 不要改变用户的浏览器窗口大小。用户有权控制自己的浏览器。 如果你改变窗口大小,你会在他们面前失去信用。

7. 不必要时不要让用户注册。直白地讲,我上网是为了获取信息,不是为了别的。 不要强迫我注册并留下我的电子邮件以及其他信息,除非特别必要(比如你 能提供的消息非常有价值)。

8. 不要在未经访问者同意的情况下为他们订阅电子杂志。 不要在访问者注册时自动给他们订阅电子杂志。 不请自来的邮件可不是个交朋友的好办法。

9. 不要过多使用Flash。Flash不仅会增加网站的读取时间, 过度使用甚至会让访问者感到不快。只有当静态页面无法表达你的意图时 才使用Flash。

10. 不要播放音乐。早些年Web开发者都喜欢在网站中集成音乐,结果他们失败了。 记住,永远不要使用音乐。

11. 当你必须使用声音时,让用户启动它。有时你必须使用声音文件, 比如你要给用户发送一份演讲,或者你的教程包含声音。这没问题,但要让用户来控制, 让用户点击“播放”按钮,别在打开网页的瞬间播放声音。

12. 不要让标志弄乱你的网站。社交网络和社区的标志会让你的网站看起来十分不专业。 就算是奖章和荣誉等标志也应当放到“关于我们”页面上。

13. 不要使用“点击进入”页面。用户访问到内容的步骤越少越好。

14. 注意要留下联系方式。最差的莫过于网站没有留下联系方式的了。 不仅对访问者不友好,而且对你也没好处,你会错过珍贵的反馈信息。

15. 不要影响“后退”按钮的动作。这是网站可用性的最基本的理念。 在任何情况下都不能影响“后退”按钮的动作。比如,打开新窗口会破坏它, 某些Javascript链接也会破坏它。

16. 不要用闪烁的文字。除非你的访问者来自1996年,否则别用闪烁文字。

17. 避免复杂的URL结构。一个简单的基于关键字的URL结构不仅能提高你的搜索引擎排名, 还能让访问者在访问之前了解网页内容。

18. 用CSS布局,不要使用表格。HTML表格曾经被用于页面布局, 但没有必要拘泥于此,尤其是在CSS诞生之后。CSS更快、更稳定, 并能提供更多的特性。

19. 保证用户可以搜索整个网站。搜索引擎带来因特网革命的原因,就是 它使得信息查找变得十分容易。别在你的网站上唱反调。

20. 避免使用下拉菜单。用户应当直观地看到所有导航选项。 下拉菜单会造成混乱,并且会隐藏访问者真正要找的信息。

21. 使用文字做导航栏。文字导航不仅速度快,而且更稳定。 例如,有些用户上网时会关闭图片。

22. 如果需要链接到PDF文档,一定要注明。你一定有过点击链接之后, 浏览器就像死掉一样等待Acrobat Reader启动,只为了打开一个(你不想看的)PDF? 这是个不小的麻烦,因此一定要在指向PDF的链接旁特别说明,使用户可以采取相应措施。

23. 不要用多种版本让访问者迷惑。你想用哪种带宽?56Kbps?128Kbps?Flash版还是HTML版? 嗨,我只想快点看到内容!

24. 不要在内容中混合广告。在内容中混合广告(如Adsense)也许会增加短期内的广告点击率, 但从长远角度来看,这会减少网站的人气。愤怒的用户会离开的。

25. 使用简单的导航结构。过犹不及。这个规则通常适用于人和选择上。 确保你的网站的导航结构单纯简洁。你不想让用户在查找信息时遇到麻烦吧?

26. 避免内容介绍。别强迫用户在访问到真正内容之前看某些东西。 这很令人愤怒,除非你提供的信息是用户必须的,否则他不会等下去。

27. 不要使用FrontPage。这一点也适用于其他廉价的HTML编辑器。 它们让页面设计变得更方便,但其输出结果将会非常低级,不兼容不同的浏览器, 并且会包含错误。

28. 保证你的网站兼容大部分浏览器。浏览器并不完全相同,在解释CSS和其他 语言的方法也相差甚远。不管你是否愿意,你应当让网站兼容市面上的常用浏览器, 否则你会永远地失去部分读者。

29. 保证在链接上添加有意义的文字。以前我经常犯这个错误。告诉人们“点击这里”很容易, 但这没有效果。要保证链接文字有意义。它使得访问者知道点击链接之后将出现什么, 也能为链接指向的外部站点带来SEO效果。

30. 不要在状态栏中隐藏链接。用户还必须能在状态栏中看到链接指向哪里。 如果你隐藏了链接(即使是由于其他原因),那么你也会丧失信誉。

31. 使链接可见。访问者应能轻易识别出哪些能点击,哪些不能。 确保链接的颜色有强烈的对比(标准的蓝色通常是最好的)。可能的话, 最好加上下划线。

32. 不要在普通文本上添加下划线或者颜色。除非特别需要,否则不要为普通文字添加下划线。 就像用户需要识别哪些能点击一样,他们不应当将本不能点击的文字误认为能够点击。

33. 改变访问过的链接的颜色。这一点对于提高网站可用性非常重要。 改变访问过的链接颜色有助于用户在网站中定位,确保他们不会不经意地 访问同一页面两次。

34. 不要使用动态GIF。除非你有需要动画的广告条,否则避免使用动态GIF。 它会使网站看上去很业余,并且会分散访问者的注意力。

35. 给图像添加ALT和TITLE属性。ALT和TITLE不仅会带来SEO效果,而且 对盲人 使用纯文本浏览器的人 盲人有很大帮助。(感谢小乐同学指正错误)

36. 不要用令人不快的颜色。如果用户连续阅读10分钟后觉得头疼, 那么你最好选择别的配色方案。根据你的目的决定设计(例如,创造一种氛围 使得用户将注意力放在网站内容上,等等)。

37. 不要弹出窗口。这一点涉及任何种类的弹出窗口。即使用户要求使用, 弹出窗口也不宜使用,因为它会被弹出窗口拦截功能阻拦。

38. 不要使用Javascript做链接。远离那些点击之后执行一小段Javascript的链接, 它们经常给用户带来麻烦。

39. 在页面底部放置有意义的链接。访问者在找不到所需信息时通常会滚动到页面最底端。 作为最后的手段,你应当在页面底部放一个“联系我们”页面的链接。

40. 避免网页过长。如果用户老是需要滚动才能看到内容,他通常会采取的做法是 跳过它们。如果你的网站正好如此,那么应当缩短内容并优化导航结构。

41. 禁止使用水平滚动条。虽然垂直滚动条可以接受,但水平滚动条却远非如此。 现在的流行分辨率是1024×768,要确保网站能容纳在其中。

42. 禁止出现拼写或语法错误。这不是网站设计的错,但却是影响网站整体质量的重要因素。 确保链接和文字中没有拼写或语法错误。

43. 如果你使用图片认证,要保证能看清其字符。有些网站将图片认证作为对抗垃圾评论的方法, 或是在注册表单上使用。其中有个问题就是,用户经常需要叫上全家人来讨论图片上到底是什么字母。

分类: 转载 标签:

终于用上AGN5100无线网卡了

2009年11月18日 16hot 没有评论

自从换了X200的笔记本后,自带的Intel AGN5100网卡,在FreeBSD一直没有驱动,一直无法使用。后来不得已买了个D-Link 的USB无线网卡,能用,但终究是不方便。

今天google了下,在freebsd论坛上找到了dehpij号召大家测试5100网卡驱动的帖子,并且看到有些朋友已经成功使用上了,于是自己也按帖子上的方法安装了驱动。能够使用了。

在不验证和WEP验证模式下都成功使用上AGN5100网卡了。

不过我遇到些问题,看别人的5100卡,支持300M,而我的才54M。我已经将我的情况在FreeBSD论坛上贴出了,等待消息。

具体帖子: http://forums.freebsd.org/showthread.php?t=8041

有需要的朋友,不妨联系我。

分类: BSD/linux 标签:

什么是CPM、CPC、CPA、CPS广告

2009年11月18日 16hot 没有评论

 

CPM(Cost Per Mille,或者Cost Per Thousand;Cost Per Impressions):每千人访问成本。CPM(千人成本)指的是广告投放过程中,听到或者看到某广告的每一人平均分摊到多少广告成本。假设单价是 10元/CPM的话,意味着每一千个人次看到这个广告的话就收10元。

CPC(Cost Per Click;Cost Per Thousand Click-Through):每点击成本。以每点击一次计费。一般是24小时内,不重复IP点击一次的成本。

CPA(Cost Per Action):每行动(回响)成本。CPA计价方式是指按广告投放实际效果计费。

CPS(Cost Per Sales):以实际销售产品数量来换算广告刊登金额。

了解了这几种广告形式的基本概念之后,大致上其实已经知道哪种类型的网站适合做哪一种类型的广告了。

CPM广告,适合流量大,或者是IP少但是PV较高的网站,例如论坛。CPM广告对站长比较有利。
CPC广告,适合产品类博客,例如介绍数码产品的博客,或者是介绍其他的一些产品的博客。做CPC广告最好是做那些竞争比较激烈的产品。例如医疗类的,或者是保健产品类的。因为竞争激烈,单价会比较高。
CPA广告,适合站长类站点,网赚类站点,尤其是下载类站点。
CPS广告,适合折扣类站点,折扣类论坛。产品类站点应用的好,也有不错的效果。例如专门有很多人通过做书籍类,或者是光碟类的资讯来通过CPS赚钱。

总体而言,CPM最好做最保险,CPS最难做最容易赚大钱,CPA和CPS应用得当也有不错的效果。没有任何一种广告形式是万能的,都得根据网站的主题来调整。就目前的测试结果来看,最适合的还是CPA形式,CPS基本没戏:)

网站赚钱,其实还是分为两类。一类是先通过确定广告类型来填充网站内容,一类则是先有内容再来挑选适合的广告类型。前者会比较累,但是因为目标明确更容易赚的更多;后者则比较轻松,但是绝大部分这类站长赚的都不多。

就我自己的理解,从长远来看,CPS绝对是王道。如果打算专职从事网赚的话,还得挑选CPS来做。

分类: 转载 标签:

nginx && libevent 的一些链接

2009年11月12日 16hot 没有评论

最近两天在学习nginx,顺便也学习了下libevent。将相关的一些技术文章地址摘录如下:

http://night9.cn/category/nginx

http://amix.dk/blog/viewEntry/19414

http://www.igvita.com/2008/02/11/nginx-and-memcached-a-400-boost/

http://wiki.nginx.org/Nginx3rdPartyModules

http://code.google.com/p/php-redis/

http://blog.sina.com.cn/iyangjian

 如何写nginx module

http://timyang.net/web/nginx-module/

http://code.google.com/p/redis/

 

另外,计划使用libevent改写扫描和发送报警引擎。

分类: C/C++ 标签:

【zz】Network Programming Using Libevent

2009年11月12日 16hot 没有评论
from http://blog.gslin.net

在課堂上學過 Unix Network Programming 後,我們知道在處理多 User 時會有幾種方法解決:

   1. 一個新的 Connection 進來,用 fork() 產生一個 Process 處理。   2. 一個新的 Connection 進來,用 pthread_create() 產生一個 Thread 處理。   3. 一個新的 Connection 進來,丟入 Event-based Array,由 Main Process 以 Nonblocking 的方式處理所有的 I/O。

這三種方法當然也都有各自的缺點:

   1. 用 fork() 的問題在於每一個 Connection 進來時的成本太高。   2. 用 Multi-thread 的問題在於 Thread-safe 與 Deadlock 問題難以解決,另外有 Memory-leak 的問題要處理。   3. 用 Event-based 的方式在於實做上不好寫,尤其是要注意到事件產生時必須 Nonblocking,於是會需要實做 Buffering 的問題,而 Multi-thread 所會遇到的 Memory-leak 問題在這邊會更嚴重。而在多 CPU 的系統上沒有辦法使用到所有的 CPU resource。

當然,針對前面兩項有各自的解法:

   1. 以 Poll 的方式解決:當一個 Process 處理完一個 Connection 後,不直接死掉,而繼續回到 accept() 的狀態繼續處理,但這樣會遇到 Memory-leak 的問題,於是採用這種方式的人通常會再加上「處理過 N 個 Connection 後死掉,由 Parent Process 再 fork() 一隻新的」。最有名的例子是 Apache 1.3。   2. Thread-safe 的問題可以透過自己撰寫,或是尋找其他 Thread-safe Library 直接使用。Memory-leak 的問題可以試著透過 Garbage Collection Library 分析出來。Apache 2.0 的 Thread MPM 就是使用這個模式。

然而,目前高效率的 Server 都偏好採用 Event-based,一方面是沒有 Create Process/Thread 所造成的 Overhead,另外一方面是不需要透過 Shared Memory 或是 Mutex 在不同的 Process/Thread 之間交換資料。

然而,Event-based 在實做上的幾個複雜的地方在於:

   1. select() 與 poll() 的效率過慢,造成每次要判斷「有哪些 Event 發生」這件事情的成本很高,這在 BSD 支援 kqueue()、Linux 支援 epoll()、Solaris 支援 /dev/poll 後就解決了,但這兩組 Function 都不是 Standard,於是在不同的平台上就必須再改一次。   2. 因為 Nonblocking,所以在 write() 或是 send() 時滿了需要自己 Buffering。   3. 因為 Nonblocking,所以不能使用 fgets() 或是其他類似的 function,於是需要自己刻一個 Nonblocking 的 fgets()。但是使用者所丟過來的資料又不能保證在一次 read() 或 recv() 就有一行,於是要自己做 Buffering。

實際上這三件事情在 libevent 都有 Library 處理掉了。

另外值得注意的一點在於 libevent 使用的是 3-clause BSD license 而非 GPL,所以在不想公開程式碼 (像是商業用途) 的情況下會比其他的 Library 適合。

接下來要談的是 libevent 要如何使用,不過為了方便起見,我們直接寫一個很簡單的 Time Server 來當作例子:當你連上去以後 Server 端直接提供時間,然後結束連線。

在這些例子裡面我以 FreeBSD 6.0 當作測試的平台,另外使用 libevent 1.1a 當作 Event-based Library,Compile 時請使用 gcc -I/usr/local/include -o timeserver timeserver.c -L/usr/local/lib -levent (如果 libevent 的 Header 與 Library 放在 /usr/include 與 /usr/lib 下的話可以省略這兩個參數)。

原始程式碼在文章的最後頭。

event_init() 表示初始化 libevent 所使用到的變數。

event_set(&ev, s, EV_READ | EV_PERSIST, connection_accept, &ev) 把 s 這個 File Description 放入 ev (第一個參數與第二個參數),並且告知當事件 (第三個參數的 EV_READ) 發生時要呼叫 connection_accept() (第四個參數),呼叫時要把 ev 當作參數丟進去 (第五個參數)。

其中的 EV_PERSIST 表示當呼叫進去的時候不要把這個 event 拿掉 (繼續保留在 Event Queue 裡面),這點可以跟 connection_accept() 內在註冊 connection_time() 的程式碼做比較。

而 event_add(&ev, NULL) 就是把 ev 註冊到 event queue 裡面,第二個參數指定的是 Timeout 時間,設定成 NULL 表示忽略這項設定。

最後的 event_dispatch() 表示進入 event loop,當 Queue 裡面的任何一個 File Description 發生事件的時候就會進入 callback function 執行。

這隻程式非常粗糙,有很多地方沒有注意到 Blocking 的問題,這點我們就先不管了。當跑起來以後你就可以連到 port 7000,就會出現類似下面的結果:gslin@netnews [~] [3:14/W5] t 0 7000

    gslin@netnews [~/work/C] [3:15/W3] t 0 7000    Trying 0.0.0.0...    Connected to 0.    Escape character is '^]'.    Fri Nov 25 03:15:10 2005    Connection closed by foreign host.

最基本的使用就是這樣了,你可以 man event 看到完整的說明。

這是 timeserver.c:

#include <netinet/in.h>#include <sys/socket.h>#include <sys/types.h>#include <event.h>#include <stdio.h>#include <time.h>

void connection_time(int fd, short event, struct event *arg){    char buf[32];    struct tm t;    time_t now;

    time(&now);    localtime_r(&now, &t);    asctime_r(&t, buf);

    write(fd, buf, strlen(buf));    shutdown(fd, SHUT_RDWR);

    free(arg);}

void connection_accept(int fd, short event, void *arg){    /* for debugging */    fprintf(stderr, "%s(): fd = %d, event = %d.n", __func__, fd, event);

    /* Accept a new connection. */    struct sockaddr_in s_in;    socklen_t len = sizeof(s_in);    int ns = accept(fd, (struct sockaddr *) &s_in, &len);    if (ns < 0) {        perror("accept");        return;    }

    /* Install time server. */    struct event *ev = malloc(sizeof(struct event));    event_set(ev, ns, EV_WRITE, (void *) connection_time, ev);    event_add(ev, NULL);}

int main(void){    /* Request socket. */    int s = socket(PF_INET, SOCK_STREAM, 0);    if (s < 0) {        perror("socket");        exit(1);    }

    /* bind() */    struct sockaddr_in s_in;    bzero(&s_in, sizeof(s_in));    s_in.sin_family = AF_INET;    s_in.sin_port = htons(7000);    s_in.sin_addr.s_addr = INADDR_ANY;    if (bind(s, (struct sockaddr *) &s_in, sizeof(s_in)) < 0) {        perror("bind");        exit(1);    }

    /* listen() */    if (listen(s, 5) < 0) {        perror("listen");        exit(1);    }

    /* Initial libevent. */    event_init();

    /* Create event. */    struct event ev;    event_set(&ev, s, EV_READ | EV_PERSIST, connection_accept, &ev);

    /* Add event. */    event_add(&ev, NULL);

    event_dispatch();

    return 0;}

這次要談的跟 Network Programming 沒有直接的關係。

在寫 Nonblocking Network Program 通常要處理 Buffering 的問題,但並不好寫,主要是因為 read() 或 recv() 不保證可以一次讀到一行的份量進來。

在 libevent 裡面提供相當不錯的 Buffer Library 可以用,完整的說明在 man event 的時候可以看到,最常用的應該就是以 evbuffer_add()、evbuffer_readline() 這兩個 Function,其他的知道存在就可以了,需要的時候再去看詳細的用法。

下面直接提供 libevent-buff.c 當作範例,編譯後看執行結果,再回頭來看 source code 應該就有感覺了:

#include <sys/time.h>#include <event.h>#include <stdio.h>

void printbuf(struct evbuffer *evbuf){    for (;;) {        char *buf = evbuffer_readline(evbuf);        printf("* buf = %p, the string = "e[1;33m%se[m"n", buf, buf);        if (buf == NULL)            break;        free(buf);    }}

int main(void){    struct evbuffer *evbuf;

    evbuf = evbuffer_new();    if (evbuf == NULL) {        fprintf(stderr, "%s(): evbuffer_new() failed.n", __func__);        exit(1);    }

    /* Add "gslin" into buffer. */    u_char *buf1 = "gslin";    printf("* Add "e[1;33m%se[m".n", buf1);    evbuffer_add(evbuf, buf1, strlen(buf1));    printbuf(evbuf);

    u_char *buf2 = " is reading.nAnd he is at home.nLast.";    printf("* Add "e[1;33m%se[m".n", buf2);    evbuffer_add(evbuf, buf2, strlen(buf2));    printbuf(evbuf);

    evbuffer_free(evbuf);}
分类: C/C++ 标签: