|
不刷新聊天室的问题2 ~ admin
用PHP完成这种功能我们早已经实现,而且极其easy。
稍加变化,我们还开发出许多比这更有意思的功能。 不过由于曾经签过保密协议,所以不能贴原码出来, 只大概提示一下原理。 Frame#1: <?php echo "显示各种初始信息n"; 无穷循环开始 { if(共享数据结构中有新数据) //共享数据结构可理解为共享内存、共享 文件、数据库等等 { echo "显示新数据n"; 输出至客户端浏览器; } sleep(5);由于根本无必要时刻监视共享数据结构,所以可以释放一些系统时 间,具体时间因子可根据实际情况设定 } ?> Frame#2: <? 处理客户端的数据输入,并提交至服务器、更新服务器端共享数据结构中的数据 : ?> 以上只是点到为止,嘿嘿,这就是一层窗户纸,捅破了就...... 下面就是我一夜未眠的一点所得,为了赶时间,偷了 很多的懒(:^),比如少了很多出错判断,连文件锁都 没加,也可用共享内存来代替文件spool,用线程库来写, 可能效率会高一些。这只是一个技术演示程序,希望起 到一个抛砖引玉的作用。待我把它完善了,再给大家, 一起探讨。 /* Chat Server Test program by leex(1999/12/6 4:51) compile under redhat linux 6.0 leex@990.net */ #include <stdio.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <signal.h> #include <sys/wait.h> #define SERV_PORT 6666 #define INTERVAL 3 #define SPOOLFILE "spool.dat" #define MAXLINE 4096 #define TALKERNAMELEN 20 #define MSGLEN 80 typedef struct{ int magic; int msgcount; }SPOOLFILEHEADER; typedef struct{ char talkername[TALKERNAMELEN]; char msg[MSGLEN]; }MSGBODY; void str_serv(int connfd,struct sockaddr_in *cliaddr); void createspool(); void addtospool(char *talkername,char *chatmsg); int main() { int listenfd,connfd; struct sockaddr_in servaddr,cliaddr; int clilen; int childpid; void sig_child(); createspool(); listenfd = socket(AF_INET,SOCK_STREAM,0); bzero(&servaddr,sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(SERV_PORT); bind(listenfd,&servaddr,sizeof(servaddr)); listen(listenfd,5); signal(SIGCLD,sig_child); for(;;){ clilen = sizeof(cliaddr); connfd = accept(listenfd,&cliaddr,&clilen); if((childpid = fork()) == 0){ close(listenfd); str_serv(connfd,&cliaddr); exit(0); } close(connfd); } } void str_serv(int connfd,struct sockaddr_in *cliaddr) { char *r200 = "HTTP/1.1 200n"; char *header = "Content-type:text/htmln"; char *end = "n"; char *autoscroll = "<SCRIPT LANGUAGE="JavaScript1.1"> <!-- var autoScrollOn = 1;var scrollOnFunction;var scrollOffFunction; function scrollit(){if(!parent.d.document.inputform.as.checked){autoSc rollOn=0;return true;}else {autoScrollOn=1;StartUp();return true;}} function scrollWindow( ){if ( autoScrollOn == 1 ){this.scroll(0, 65000 );setTimeout('scrollWindow()',200);}} function scrollOn( ){autoScrollOn = 1;scrollWindow( );} function scrollOff( ){autoScrollOn = 0;} function StartUp( ){this.onblur = scrollOnFunction;this.onfocus = scr ollOffFunction;scrollWindow( );} scrollOnFunction = new Function('scrollOn( )') scrollOffFunction = new Function('scrollOff( )') StartUp(); //--></script>"; char *info = "你 说:这是一条测试信息!<br> "; int curpos; FILE *file; SPOOLFILEHEADER fheader; MSGBODY msg; char chatmsg[MAXLINE]; int i; curpos = 0; addtospool((char *)inet_ntoa(cliaddr->sin_addr)," 各位朋友,大家好"); write(connfd,r200,strlen(r200)); write(connfd,header,strlen(header)); write(connfd,end,strlen(end)); write(connfd,"<HTML>",6); write(connfd,autoscroll,strlen(autoscroll)); while(1){ file = fopen(SPOOLFILE,"r"); fread(&fheader,sizeof(SPOOLFILEHEADER),1,file); fseek(file, sizeof(SPOOLFILEHEADER)+curpos*sizeof(MSGBODY), SEEK_SET ); for(i=0;i<fheader.msgcount-curpos;i++){ fread(&msg,sizeof(MSGBODY),1,file); snprintf(chatmsg,MAXLINE,"%s 说:%s<br>", msg.talkername,msg.msg); write(connfd,chatmsg,strlen(chatmsg)); } fclose(file); curpos = fheader.msgcount; write(connfd,info,strlen(info)); sleep(INTERVAL); } write(connfd,"</HTML>",6); } void sig_child() { int pid,stat; while((pid = waitpid(-1,&stat,WNOHANG))>0) addtospool("SYSOP","哈哈,某人掉线了!^_^ "); } void createspool() { FILE *file; SPOOLFILEHEADER fheader; fheader.magic = 8888; fheader.msgcount = 0; file = fopen(SPOOLFILE,"w+"); fwrite(&fheader,sizeof(SPOOLFILEHEADER),1,file); fclose(file); } void addtospool(char *talkername,char *chatmsg) { FILE *file; SPOOLFILEHEADER fheader; MSGBODY msg; snprintf(msg.talkername,TALKERNAMELEN,"%s",talkername); snprintf(msg.msg,MSGLEN,"%s",chatmsg); file = fopen(SPOOLFILE,"a"); fwrite(&msg,sizeof(MSGBODY),1,file); fclose(file); file = fopen(SPOOLFILE,"r+"); fread(&fheader,sizeof(SPOOLFILEHEADER),1,file); fheader.msgcount += 1; fseek(file, 0L, SEEK_SET); fwrite(&fheader,sizeof(SPOOLFILEHEADER),1,file); fclose(file); } |