preload
五月 21

剛剛才發現原來CentOS 5.3早在3/1就出來了, 但是國內的許多ftp server 竟然都還沒放上去.
想抓5.3的朋友, BT抓比較快啦.
CD版:
http://mirror.centos.org/centos/5.3/isos/i386/CentOS-5.3-i386-bin-1to6.torrent
http://mirror.centos.org/centos/5.3/isos/x86_64/CentOS-5.3-x86_64-bin-1to7.torrent
DVD版:
http://mirror.centos.org/centos/5.3/isos/i386/CentOS-5.3-i386-bin-DVD.torrent
http://mirror.centos.org/centos/5.3/isos/x86_64/CentOS-5.3-x86_64-bin-DVD.torrent

真想把我的Server 更新到5.3版. 只是想到要重裝就很累.
不過, 用下列指令就可以輕鬆的把我的CentOS 5.2 升級到5.3. 免去重裝的辛苦.

(1) 先用 ‘yum list updates’ 來取得最新的package list.
(2) 然後執行 ‘yum update’ 來更新所有的套件.
(3) 等到更新完後, 執行下列指令確定是否更新到5.3
‘rpm -q centos-release’
若一切都沒錯的話, 應該會看到如下字串:
‘centos-release-5-3.el5.centos.1′

以上! 搞定~~

五月 19


若有架e-mail server的朋友, 可以用這個Open Relay測試來測試你的server是否有Open Relay.
若有的話, 趕緊更改設定吧, 以免被別人拿來當發垃圾信件的主機.

五月 18

6年前, 當我用過BeyondCompare這套Diff軟體後, 在Windows中, 再也沒有任何一套Diff軟體, 即使是免費的Diff軟體, 也無法讓我看的上眼. 因為BeyondCompare實在太好用了.
Continue reading »

五月 08


這幾天, 因為無聊, 上網看了一些socket的function, 順手抄了一個簡單的socket程式.
但是這程式總是很不穩定.
怪怪! server端的程式, run 了第二次後, bind() 就會產生』Address already in use』的錯誤訊息.

上Google查了一下, 才知道bind() 之後, 若程式已經結束, 雖然已經正常把socket給close() 了,
但是kernel並不會release這個TCP 的connectioin, 它的狀態會keep 在』TIME_WAIT』狀態. (可以用netstat -t查詢)
要好幾分鐘後, kernel才會release 掉.
怪怪!! 搞不懂為何要做成這樣?? 算了! 找到解答就好.
在bind() 之前加上

setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, reuseaddr_len);

來告訴bind(), 若這個address 假設已經被佔用了, 那就重複使用吧.
完整的code 如下:
Server端:


#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <signal.h>    /* signal name macros, and the signal() prototype */

#define DAEMON_LOCK "/tmp/hao_lock"
int listenFd, connectFd;
char    ttt[]="12345";

void catch_int(int sig_num);

pid_t CheckLock(void)
{
  pid_t me;
  FILE * fp; 

  fp = fopen(DAEMON_LOCK,"rt");
  if (fp==NULL) return 0;
  fscanf(fp,"%d",&me);
  fclose(fp); 

  return me;
} 

pid_t WriteLock(void)
{
  pid_t me;
  FILE *fp; 

  me = getpid(); 

  fp = fopen(DAEMON_LOCK,"w");
  fprintf(fp,"%d",me);
  fclose(fp); 

  return me;
} 

int CleanLock(void)
{
  return (unlink(DAEMON_LOCK)==0);
} 

int init_server(int type, const struct sockaddr *addr, socklen_t alen, int qlen)
{
    int fd;
    int err = 0;
    int reuseaddr = 1;
    socklen_t reuseaddr_len;

    if((fd = socket(addr->sa_family, type, 0)) < 0)
        return (-1);

    reuseaddr_len = sizeof(reuseaddr);
    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, reuseaddr_len);

    if(bind(fd, addr, alen) < 0) {
        err = errno;
        goto errout;
    }
    WriteLock();

    if((type == SOCK_STREAM) || (type == SOCK_SEQPACKET)) {
        if(listen(fd, qlen) < 0) {
            err = errno;
            goto errout;
        }
    }
    return (fd);
errout:
    close(fd);
    errno = err;
    return(-1);
}

int main(int argc, char *argv[])
{
    struct sockaddr_in serverAddr;
    pid_t   myself;

    time_t  ticks;
    char    buf[1024];

    listenFd = -1;
    connectFd = -1;

    /* find myself */
    myself = CheckLock();
    if (myself!=0) {
        printf("Existing a copy of chess daemon[pid=%d], leave now.\n",myself);
        exit(1);
    } 

    /* set the INT (Ctrl-C) signal handler to 'catch_int' */
    signal(SIGINT, catch_int);

    bzero(&serverAddr, sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    // any internet interface on ths server.
    serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    serverAddr.sin_port        = htons(13000);

    if((listenFd = init_server(SOCK_STREAM, (const struct sockaddr *)&serverAddr, sizeof(serverAddr), 5)) < 0) {
        perror("init_server");
        exit(1);
    }
    printf("Init Done..\n");
    for( ; ; ) {
        if((connectFd = accept(listenFd, NULL, NULL)) == -1) {
            perror("\n accept() error");
            exit(1);
        }
        fputs("Server: Connected!!\n",stdout);
        ticks = time(NULL);
        sprintf(buf,"%.24s\r\n", ctime(&ticks));
        write(connectFd, buf, strlen(buf));

        shutdown(connectFd, 2);
        close(connectFd);
    }
    return 0;
}

void catch_int(int sig_num)
{

    signal(SIGINT, catch_int);

    if(listenFd > 0)
        close(listenFd);
    CleanLock();

    printf("\n Done\n");
    exit(0);

}

Client端:


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

#define MAXSLEEP 128
int connect_retry(int sockfd, const struct sockaddr *addr, socklen_t alen)
{

    int nsec;
    // Try to connect with exponential backoff.
    for(nsec = 1; nsec <= MAXSLEEP; nsec <<= 1) {
        if(connect(sockfd, addr, alen) == 0) {
            // Connection accepted.
            return(0);
        }
        // Delay before trying again.
        printf("Retry..\n");
        if(nsec <= MAXSLEEP/2)
            sleep(nsec);
    }
    return (-1);
}

int main(int argc, char *argv[])
{
    struct sockaddr_in serverAddr;
    int sockFd, n;
    char buf[1025];

    if(argc != 2) {
        fputs("usage: a.out \n", stdout);
        return -1;
    }

    // set a tcp/ip socket
    sockFd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockFd <= -1) {
        perror("\n Create socket error!");
        exit(1);
    }

    bzero(&serverAddr, sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port   = htons(13000);
    // host IP # in dotted decimal format !
    inet_pton(AF_INET, argv[1], &serverAddr.sin_addr);

    connect_retry(sockFd, (struct sockaddr *)&serverAddr, sizeof(serverAddr));

    while(( n = read(sockFd, buf, sizeof(buf))) > 0) {
        buf[n] = 0;
        fputs(buf, stdout);
    }
    shutdown(sockFd, 2);
    close(sockFd);
    return 0;
}

以上的code, 大部分都是抄來的, 故不保證沒有問題.

若是使用AF_UNIX方式來連接, 那就不是上述方式來解決.
因為AF_UNIX方式會產生一個file, 只要離開程式之前, 呼叫unlink() 把它delete掉即可.
參考:
http://blog.chinaunix.net/u2/67414/showart_1889821.html

五月 04


長久以來, 我一直在尋找好用且免費的Editor.
我目前在用的Editor是Jedit, 它幾乎是我心中最完美的Editor.
可以在Windows/Linux/Mac 中使用.
只可惜的是, 它有點慢, 在一些慢速的CPU上, 如Atom, 跑起來顯得有點吃力.
還有就是, 在Linux環境下, 總覺得穩定度似乎得再加強(或許是Sun JRE的問題??).
因此, 我一直再尋找Linux能跟Jedit一樣好用的軟體.

曾經用了一套MadEdit, 算是不錯了.
但是在捲動畫面的時候, 還蠻lag的.

OK! 回歸正題, 剛剛又看到一套Open Source的Editor: Geany
畫面不錯, 如下:
geany_main

有Tab, 以及畫面左邊有Function List, 正是我所需要的功能. 雖然目前只到0.17版, 但是有空一定要裝來玩玩.

五月 04

喜歡嚐鮮的朋友. 可以到Microsoft網站這裡去抓吧.
可以免費申請到Product Key. 這個key可以使用一年喔~~

四月 30


剛剛想要在一個JPG檔裡畫個小圈圈.
突然想到, Mac下好像沒有內建類似小畫家的程式.

這時想的GIMP在各種平台上都有對應的版本.
立刻下載下來使用.

但是問題來了~~ 對於我這個很少用繪圖軟體的人而言, 天啊~~ GIMP怎會這麼複雜啊~~
想要用紅色畫個小圈圈都找不到怎麼用. 是我太白痴了嗎??!!

後來受不了了, 再上網找找看.
終於找到一個簡單, 類似小畫家的軟體PaintBrush
簡單明瞭多了 :) , 適合我這種繪圖白痴使用 XD.
paintbrush

四月 28

或許你會有點疑惑, 這是啥東西的??
若你的電腦的硬碟曾經壞掉, 而且你的系統是Windows, 你應該會有很深的痛吧.
即使是你有備份資料的習慣, 在硬碟壞掉後, 想要Windows系統完完全全的恢復到壞掉之前的樣子,
包含所有的應用程式, 資料, 和所有的設定等等, 簡直比登天還難.
後來我改用Mac後, 它的Time Machine真的是備份中最完美的方案.
我曾經只花了1小時左右,只按了2~3個按鈕, 就把Mac的所有的資料(含系統,應用程式, 所有的設定)輕鬆的轉到新的硬碟, 而且硬碟還是不同容量的喔!!. 只要1~2小時, 工作就可以立刻恢復, 完全不用怕硬碟突然壞掉. 這個經驗, 是我在Windows上從未享受到, 也無法享受到的超級愉快的經驗.

經過我這樣描述, Windows的使用者們, 是不是會流口水啊??
看來, Windows愛好者們, 似乎有救了.
剛剛在這看到一個有趣的東西: Seagate Replica
seagate_replica
它只做一件是: 自動備份你的資料(含系統, 資料, 設定, 垃圾等等 就是你硬碟裡的所有東西啦).
雖然我沒看到真正的實物, 但是這規格看起來, 真的好像有點Mac 版的Time Machine感覺耶~~

四月 27

雖然我對於這相機沒啥興趣.
但是這個廣告的拍攝手法, 我非常喜歡.
Enjoy It!!

四月 27

剛剛在看Jservblog時, 看到這個新網站0xlab.
真的很高興, 台灣也有一群有實力, 又對於OpenSource如此熱衷的工程師能夠聚在一起, 為OpenSource而努力.

以前我一直以為, 台灣大部分實力很強的工程師, 都為了賺錢, 而不願在OpenSource上有所著墨.
或許是在台灣風氣的關係, 工程師們的時間都非常的長, 以致於根本沒時間作其他的事. 若工作時間短一點, 都會被老闆們盯.
為了吃飯, 就不得不放棄一些夢想.

也是有少部分的工程師, 在OpenSource上努力, 大多是1個人單打獨鬥. 很難有大Project出現.
目前在台灣OpenSource大多是由學術界在努力.

如今, 在0xlab我似乎看到一些不一樣了. 在這裡, 為0xlab加油.