最近在玩android,突然想做一个私人聊天工具,缺乏一个服务器,于是自己想写一个c实现的daemon select server
来源:互联网 发布:icloud恢复备份mac 编辑:程序博客网 时间:2024/05/16 07:09
我喜欢站在巨人的肩膀上来做事,因为学习的道路是曲折的,你不可能将所有的东西都搞懂搞透了才去做一件事情,那样,你永远做不了大事。思路大概是这样的
1、找一个daemon程序来看看,了解起原理。
2、找一个select server程序来看看,了解起原理。
3、将两者融合起来,就是一个daemon 的select server了。
为什么要daemon,因为,我们server脱离终端,不想因为终端连接断开啥的一些而导致我们的server程序退出。当然,讲得有些不够准确,但是好处多多,大家可以去google所stackvoer上找。
为什么要用select而不用epoll,没有错,epoll确实比select要更加好用,但是,出于学习的目的,我觉得select,poll,epoll都该了解下,时间有限,写个select玩玩,epoll强大,以后server升级的方向就是换成epoll,还有一点考虑是epoll是linux才有的,而且貌似先前linux版本还没有,unix上,据我看到的一个较老的资料上讲,没有epoll,不管怎么样,这三个都是系统调用,也就是内核帮我们去做的一件事。
程序代码如下,这是直接可以在linux上编译通过的
g++ -g -o select_server select_server.cpp
./select_server 9988
ps -ef |grep select_server
如果成功启动,就可以看到select_server 这个进程了。
/*UNIX Daemon Server Programming Sample ProgramLevent Karakas <levent at mektup dot at> May 2001To compile: cc -o exampled examped.cTo run: ./exampledTo test daemon: ps -ef|grep exampled (or ps -aux on BSD systems)To test log: tail -f /tmp/exampled.logTo test log: tail -f /tmp/select_server_v2.logTo test signal: kill -HUP `cat /tmp/exampled.lock`To terminate: kill `cat /tmp/exampled.lock`*/#include <stdio.h>#include <errno.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>#include <netinet/in.h>#include <netdb.h>#include <fcntl.h>#include <signal.h>#include "string"#define MAXMSG 512#define RUNNING_DIR "/tmp"#define LOCK_FILE "exampled.lock"#define LOG_FILE "exampled.log"#define SEREVER_CONNET_LOG "select_server_v2.log"/******************start of daemon ******************************/void log_message(char *filename,char *message){ FILE *logfile; logfile=fopen(filename,"a"); if(!logfile) return; fprintf(logfile,"%s\n",message); fclose(logfile);}void signal_handler(int sig){ switch(sig) { case SIGHUP: log_message(LOG_FILE,"hangup signal catched"); break; case SIGTERM: log_message(LOG_FILE,"terminate signal catched"); exit(0); break; }}void daemonize(){ int i,lfp; char str[10]; if(getppid()==1) return; /* already a daemon */ i=fork(); if (i<0) exit(1); /* fork error */ if (i>0) exit(0); /* parent exits */ /* child (daemon) continues */ setsid(); /* obtain a new process group */ for (i=getdtablesize();i>=0;--i) close(i); /* close all descriptors */ i=open("/dev/null",O_RDWR); dup(i); dup(i); /* handle standart I/O */ umask(027); /* set newly created file permissions */ chdir(RUNNING_DIR); /* change running directory */ lfp=open(LOCK_FILE,O_RDWR|O_CREAT,0640); if (lfp<0){ perror("can not open!"); exit(1); /* can not open */ } if (lockf(lfp,F_TLOCK,0)<0){ perror("can not lock!"); exit(0); /* can not lock */ } /* first instance continues */ sprintf(str,"%d\n",getpid()); write(lfp,str,strlen(str)); /* record pid to lockfile */ signal(SIGCHLD,SIG_IGN); /* ignore child */ signal(SIGTSTP,SIG_IGN); /* ignore tty signals */ //signal(SIGTTOU,SIG_IGN); //signal(SIGTTIN,SIG_IGN); signal(SIGHUP,signal_handler); /* catch hangup signal */ signal(SIGTERM,signal_handler); /* catch kill signal */}/******************end of daemon ******************************//***********************make select server **********************/int make_socket (uint16_t port){ int sock; struct sockaddr_in name; /* Create the socket. */ sock = socket (PF_INET, SOCK_STREAM, 0); if (sock < 0) { perror ("socket"); exit (EXIT_FAILURE); } /* Give the socket a name. */ name.sin_family = AF_INET; name.sin_port = htons (port); name.sin_addr.s_addr = htonl (INADDR_ANY); if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) { perror ("bind"); exit (EXIT_FAILURE); } return sock;} int read_from_client (int filedes){ char buffer[MAXMSG]; char log_msg[MAXMSG+128]; int nbytes; nbytes = read (filedes, buffer, MAXMSG); if (nbytes < 0) { /* Read error. */ perror ("read"); exit (EXIT_FAILURE); } else if (nbytes == 0) /* End-of-file. */ return -1; else { /* Data read. */ memset(log_msg,0x00,sizeof(log_msg)); sprintf(log_msg,"Server :got message [%s]\n",buffer ); log_message(SEREVER_CONNET_LOG,log_msg); /*Data write**/ if(write(filedes,buffer,nbytes)==-1){ perror("server write error!"); exit(EXIT_FAILURE); } return 0; }} int main (int count, char *strings[]){ int sock; fd_set active_fd_set, read_fd_set; int i; struct sockaddr_in clientname; size_t size; int port; if ( count != 2 ) { printf("usage: %s <port>\n", strings[0]); exit(0); } port=atoi(strings[1]); // make server to be a daemon server; daemonize(); /* Create the socket and set it up to accept connections. */ sock = make_socket (port); if (listen (sock, 1) < 0) { perror ("listen"); exit (EXIT_FAILURE); } /* Initialize the set of active sockets. */ FD_ZERO (&active_fd_set); FD_SET (sock, &active_fd_set); while (1) { /* Block until input arrives on one or more active sockets. */ read_fd_set = active_fd_set; if (select (FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) < 0) { perror ("select"); exit (EXIT_FAILURE); } /* Service all the sockets with input pending. */ for (i = 0; i < FD_SETSIZE; ++i) if (FD_ISSET (i, &read_fd_set)) { if (i == sock) { /* Connection request on original socket. */ int new_fd; size = sizeof (clientname); new_fd = accept (sock, (struct sockaddr *) &clientname, &size); if (new_fd < 0) { perror ("accept"); exit (EXIT_FAILURE); } fprintf (stderr, "Server: connect from host %s, port %hd.\n", inet_ntoa (clientname.sin_addr), ntohs (clientname.sin_port)); FD_SET (new_fd, &active_fd_set); } else { /* Data arriving on an already-connected socket. */ if (read_from_client (i) < 0) { close (i); FD_CLR (i, &active_fd_set); } } } }}/*end eof */
至于这么测试 ,telnet XXX.XXX.XXX.XXX 9988
顺便介绍一个命令,strace ,这个可以跟踪下系统调用。如果服务器没启动起来的话,用它来看看,到了那一步,我开始调的时候,貌似到select是出了点问题的。
呵呵,
- 最近在玩android,突然想做一个私人聊天工具,缺乏一个服务器,于是自己想写一个c实现的daemon select server
- [原创]最近学习STL,在C++库中苦寻不到BigInteger类,于是自己写了一个
- (ty--90)刚才在看MSDN时,突然想自己做一个类似的记事本,把自己平时积累的知识分类写进去,以便日后查询
- 最近在写研究jmemcache,想实现一个数据库和数据库请求的中间程序
- 最近想做一个网站
- 开始: 其实对Android我只是略知皮毛中的皮毛,但是为什么会突然想来要用Android WebView呢?哈哈,答案就是:之前写了一个ChinaNet登录的PC版(C#),于是应童鞋们要求
- 如何在自己的计算机上做一个web服务器
- 突然想写一个vc6插件
- mfc做一个网络聊天工具
- 八一建军节,写一个最近做的架构无线网络服务器的方案
- 如何做一个自己的服务器网站
- 最近学习android MVP自己写了一个练手DEMO
- 突然有了一个做c语言脚本引擎的想法
- 写一个自己的web服务器
- iOS一个简单聊天工具的实现
- 实现一个类似QQ的社交聊天工具
- 最近一直在想的一个问题
- 自己写一个Web服务器
- 透过12306五大焦点看高性能高并发系统
- PHP数据库连接具有可扩展性
- MTK开发细节
- 树状数组
- Tomcat处理HTTP请求源码分析
- 最近在玩android,突然想做一个私人聊天工具,缺乏一个服务器,于是自己想写一个c实现的daemon select server
- BroadcastReceiver中启动Activity
- 面向对象编程的PHP
- Charset 和 Encoding 的区别是什么?
- ORACLE 树形结构数据 查询某结点下全部子节点无限递归的前2个数据
- 戴尔Inspiron 15R 5537重装系统
- [转载]iOS开源资源收集~~(第三方开源库)
- Hibernate could not locate named parameter
- Android Activity 生命周期的透彻理解