📄 1041.html
字号:
<br>
#define DAEMON_LOCK "/var/chess/daemon.lock" <br>
#define DAEMON_LOG "/var/chess/daemon.log" <br>
#define DAEMON_PORT 9901 <br>
<br>
int DaemonSocket; <br>
struct sockaddr_in DaemonAddr; <br>
<br>
int ClientSocket=0; <br>
struct sockaddr_in HostAddr; <br>
<br>
void dlog(char *fmt,...) <br>
{ <br>
va_list argptr; <br>
FILE *fp; <br>
<br>
fp = fopen(DAEMON_LOG,"a+t"); <br>
va_start(argptr,fmt); <br>
vfprintf(fp,fmt,argptr); <br>
va_end(argptr); <br>
fclose(fp); <br>
} <br>
<br>
pid_t CheckLock(void) <br>
{ <br>
pid_t me; <br>
FILE * fp; <br>
<br>
fp = fopen(DAEMON_LOCK,"rt"); <br>
if (fp==NULL) return 0; <br>
fscanf(fp,"%d",&me); <br>
fclose(fp); <br>
<br>
return me; <br>
} <br>
<br>
pid_t WriteLock(void) <br>
{ <br>
pid_t me; <br>
FILE *fp; <br>
<br>
me = getpid(); <br>
<br>
fp = fopen(DAEMON_LOCK,"w"); <br>
fprintf(fp,"%d",me); <br>
fclose(fp); <br>
<br>
return me; <br>
} <br>
<br>
int CleanLock(void) <br>
{ <br>
return (unlink(DAEMON_LOCK)==0); <br>
} <br>
<br>
void report_time(void) <br>
{ <br>
time_t now; <br>
now = time(NULL); <br>
dlog("%s",asctime((const struct tm*)localtime(&now))); <br>
} <br>
<br>
static void signal_catch(int signo) <br>
{ <br>
time_t now; <br>
<br>
close(DaemonSocket); <br>
if (ClientSocket>0) close(ClientSocket); <br>
CleanLock(); <br>
now = time(NULL); <br>
dlog("Catch signal %d, leave at %s",signo,asctime((const struct tm*)localti <br>
exit(-1); <br>
} <br>
<br>
void SetupSignal(void) <br>
{ <br>
struct sigaction act; <br>
<br>
act.sa_handler = signal_catch; <br>
act.sa_flags = 0; <br>
sigemptyset(&act.sa_mask); <br>
sigaction(SIGHUP,&act,NULL); <br>
sigaction(SIGINT,&act,NULL); <br>
sigaction(SIGQUIT,&act,NULL); <br>
sigaction(SIGILL,&act,NULL); <br>
sigaction(SIGABRT,&act,NULL); <br>
sigaction(SIGIOT,&act,NULL); <br>
sigaction(SIGBUS,&act,NULL); <br>
sigaction(SIGFPE,&act,NULL); <br>
sigaction(SIGTERM,&act,NULL); <br>
} <br>
<br>
int BindSocket(void) <br>
{ <br>
<br>
DaemonSocket = socket(AF_INET,SOCK_STREAM,0); <br>
if (DaemonSocket==-1) return 0; <br>
DaemonAddr.sin_family = AF_INET; <br>
DaemonAddr.sin_port = htons(DAEMON_PORT); <br>
if (bind(DaemonSocket,&DaemonAddr,sizeof(DaemonAddr))<0) { <br>
printf("Can not bind!"); <br>
return 0; <br>
} <br>
if (listen(DaemonSocket,1024)!=0) { <br>
printf("Can not listen!"); <br>
return 0; <br>
} <br>
<br>
return 1; <br>
} <br>
<br>
int incoming_call(void) <br>
{ <br>
fd_set sock; <br>
struct timeval tv; <br>
int t; <br>
<br>
FD_ZERO(&sock); <br>
FD_SET(DaemonSocket,&sock); <br>
tv.tv_sec = 60; tv.tv_usec = 0; <br>
t = select(DaemonSocket + 1,&sock,NULL,NULL,&tv); <br>
if (t<=0||!FD_ISSET(DaemonSocket,&sock)) return 0; <br>
<br>
dlog("incoming..."); <br>
<br>
return 1; <br>
} <br>
<br>
int ConnectClient(void) <br>
{ <br>
int socksize=sizeof(HostAddr); <br>
unsigned char * addr; <br>
<br>
ClientSocket = accept(DaemonSocket,(struct sockaddr*)&HostAddr,&socksize); <br>
if (ClientSocket<0) return 0; <br>
<br>
addr = (unsigned char *)&HostAddr.sin_addr.s_addr; <br>
<br>
dlog("incoming address:%d.%d.%d.%d",addr[0],addr[1],addr[2],addr[3]); <br>
<br>
return 1; <br>
} <br>
<br>
int daemon_printf(char *fmt,...) <br>
{ <br>
char BUF[4096]; <br>
va_list argptr; <br>
<br>
va_start(argptr,fmt); <br>
vsprintf(BUF,fmt,argptr); <br>
va_end(argptr); <br>
return write(ClientSocket,BUF,strlen(BUF)); <br>
} <br>
<br>
void Log(void) <br>
{ <br>
char BUF[4096]; <br>
read(DaemonSocket,BUF,16); <br>
daemon_printf("%s",BUF[0]); <br>
} <br>
<br>
int main(int argc,char **argv) <br>
{ <br>
pid_t myself; <br>
time_t now; <br>
<br>
/* find myself */ <br>
myself = CheckLock(); <br>
if (myself!=0) { <br>
printf("Existing a copy of chess daemon[pid=%d], leave now.",myself); <br>
exit(1); <br>
} <br>
<br>
/* fork */ <br>
myself = fork(); <br>
if (myself>0) { <br>
exit(1); <br>
} else <br>
if (myself<0) { <br>
printf("Strange world! I don't like it. Quit because of pid=%d",myself); <br>
exit(1); <br>
} else { <br>
SetupSignal(); <br>
if (!BindSocket()) { <br>
printf("Can not bind socket!"); <br>
exit(1); <br>
} <br>
WriteLock(); <br>
} <br>
<br>
printf("Chess Daemon is up, have fun!"); <br>
<br>
now = time(NULL); <br>
<br>
dlog("----------------------------------------------"); <br>
dlog( <br>
"I am back! %s" <br>
"Chess Daemon comes to alive again.", <br>
asctime((const struct tm*)localtime(&now)) <br>
); <br>
<br>
do { <br>
if (incoming_call()) { <br>
<br>
if (ConnectClient()) { <br>
<br>
fd_set sock; <br>
struct timeval tv; <br>
int t; <br>
char BUF[128]; <br>
char CC[2]; <br>
int n; <br>
<br>
daemon_printf("Welcome to Chinese Chess Game Center!"); <br>
<br>
FD_ZERO(&sock); <br>
FD_SET(ClientSocket,&sock); <br>
n = 0; <br>
do { <br>
tv.tv_sec = 60; tv.tv_usec = 0; <br>
t = select(ClientSocket+1,&sock,NULL,NULL,&tv); <br>
if (t<=0||!FD_ISSET(ClientSocket,&sock)) ; <br>
read(ClientSocket,CC,1); <br>
if (CC[0]==13||CC[0]==10||CC[0]==0) { <br>
BUF[n] = 0; <br>
dlog("%s",BUF); <br>
if (strncasecmp(BUF,"exit",4)==0) { <br>
close(ClientSocket); <br>
break; <br>
} <br>
n = 0; <br>
} else { <br>
BUF[n]=CC[0]; n++; <br>
} <br>
} while (1); <br>
} <br>
} <br>
} while (1); <br>
<br>
return 1; <br>
} <br>
<br>
检验 <br>
telnet localhost 9901 <br>
<br>
在处理Connect Client时,事实上可以运用fork或thread来处理多个连线。 <br>
<br>
<br>
Linux程式设计- 5.inetd <br>
http://www.openchess.org/noitatsko/programming/ (2001-05-24 18:08:00) <br>
inetd提供被动式的伺服器服务,也就是伺服器是被使用端所启动,平时则无须存在。例如,ftp, telnetd, pop3,imap, auth等等,这些服务没有人使用时,无须启动。此外,inetd将socket转换成stdin/stdout,因而使得网路服务程式设计大大简化,您可以只用printf及fgets便可完成处理很复杂的网路协定。 <br>
<br>
-------------------------------------------------------------------------------- <br>
<br>
inetd programming <br>
利用inetd来做网路程式设计是个既简单又稳定的设计方法,您不需要考虑到复杂的socket programming。您的设计工作几乎在设计好通讯协定後就完成了,所需要的技巧,仅为简单的文字分析技巧。 <br>
goodie inet service <br>
首先,我们先来撰写一个称为goodie的服务程式。 <br>
goodie.c <br>
#include <br>
#include <br>
#include <br>
<br>
void main(void) <br>
{ <br>
printf("Welcome to goodie service!"); <br>
} <br>
<br>
这个程式很简单,不是吗? <br>
<br>
编译 <br>
gcc -o goodie goodie.c <br>
设定/etc/services及/etc/inetd.conf <br>
在/etc/services中加入以下这一行 <br>
goodie 20001/tcp <br>
<br>
其意义为goodie这项服务是在port 20001、TCP协定。 <br>
<br>
接下来在/etc/inetd.conf中加入以下这一行 <br>
<br>
goodie stream tcp nowait root /full_goodie_path_name/goodie <br>
<br>
各项参数的意义为 <br>
<br>
<br>
service_name需要为在services中存在的名称。 <br>
sock_type有很多种,大多用的是stream/dgram。 <br>
proto一般用tcp/udp。 <br>
flags有wait/nowait。 <br>
user是您指定该程式要以那一个使用者来启动,这个例子中用的是root,如果有安全性的考量,应该要改用nobody。一般来说,建议您用低权限的使用者,除非必要,不开放root使用权。 <br>
server_path及args,这是您的服务程式的位置及您所想加入的参数。 <br>
<br>
接下来重新启动inetd <br>
<br>
killall inetd <br>
inetd <br>
<br>
这样我们便建立起一个port 20001的goodie service。 <br>
现在我们来检验一下goodie是否可以执行: <br>
<br>
telnet localhost 20001 <br>
或 <br>
telnet your_host_name 20001 <br>
<br>
执行结果 <br>
Trying 127.0.0.1... <br>
Connected to localhost. <br>
Escape character is '^]'. <br>
Welcome to goodie service! <br>
Connection closed by foreign host. <br>
很简单不是吗? 信不信由您,telnet/pop3/imap/ftp都是靠这种方式建立起来的服务。 <br>
<br>
我们现在来建立一点小小的"网路协定",这个协定使我们可以输入"exit"时,离开程式,而其他的指令都是输出与输入相同的字串。 <br>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -