Crossplatform chm reader
6年前, 當我用過BeyondCompare這套Diff軟體後, 在Windows中, 再也沒有任何一套Diff軟體, 即使是免費的Diff軟體, 也無法讓我看的上眼. 因為BeyondCompare實在太好用了.
Continue reading »
這幾天, 因為無聊, 上網看了一些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
長久以來, 我一直在尋找好用且免費的Editor.
我目前在用的Editor是Jedit, 它幾乎是我心中最完美的Editor.
可以在Windows/Linux/Mac 中使用.
只可惜的是, 它有點慢, 在一些慢速的CPU上, 如Atom, 跑起來顯得有點吃力.
還有就是, 在Linux環境下, 總覺得穩定度似乎得再加強(或許是Sun JRE的問題??).
因此, 我一直再尋找Linux能跟Jedit一樣好用的軟體.
曾經用了一套MadEdit, 算是不錯了.
但是在捲動畫面的時候, 還蠻lag的.
OK! 回歸正題, 剛剛又看到一套Open Source的Editor: Geany
畫面不錯, 如下:
有Tab, 以及畫面左邊有Function List, 正是我所需要的功能. 雖然目前只到0.17版, 但是有空一定要裝來玩玩.