`
memorymyann
  • 浏览: 266319 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

15.服务器守护进程

阅读更多

前面提到过的服务器都占有控制终端。而有些进程并不需要控制终端。比如我们想写一个回射服务器(既从终端得到信息,然后将数据再返回给终端,基于UDP因为比较简单)。

 

其实这并算不上一个难题,在shell中只要在指令后加上&就可以使服务器成为一个守护进程(后台进程)。但这里还是通过代码自己来实现。

 

#include "stdio.h"
#include "stdlib.h"
#include "/programe/net/head.h"
#include "syslog.h"
#include "sys/types.h"
#include "signal.h"
#include "string.h"

#define MAXSIZE 100

int main(int argc, char ** argv) {
        openlog("echo_server2", LOG_CONS | LOG_PID, 0);
        syslog(LOG_INFO | LOG_LOCAL0, "server start....");//利用syslog来写日志

        if(fork() != 0)
                exit(0);//父进程退出

//父进程退出后,shell就认为命令结束使得子进程在后台开始运行

        setsid();

//子进程建立新的对话期,子进程继承了父进程的组进程号,该进程组的组长为父进程,所以子进程可以自己建立一个对话期,建立对话期的子进程不再有控制终端(详细可以看linux进程组,对话期)


        signal(SIGHUP, SIG_IGN);

//忽略SIGHUP信号,这个作用下个解释会提到

        if(fork() != 0)
                exit(0);

//子进程再建立一个子进程,我们称第一个子进程为P1,有P1创建的子进程为P2。P1新建了一个对话期,P1就会作为这个对话期首进程,在SVR4中,作为对话期首进程的P1如果打开一个终端设备(如果这个设备不是其它对话期的终端),则该终端设备就会自动成为这个会话期的终端。创建P2,P2不是对话期的首进程即使打开终端设备也不会把该设备变成这个对话期的终端。(打开终端设备可以通过open(/dev/....))。前面之所以要忽略掉SIGHUP信号,是因为所谓对话期的首进程P1退出时候,会向对话期前台进程组的每一个进程发送SIGHUP信号,该信号默认操作是终止进程。

        int i;
        for(i = 0; i < 64; i++) {
                close(i);
        }

//关闭从父进程继承而来的描述字,这里我们并不知道一共有多少个描述字被打开(其实因该猜到只有3个),所以以64为标准,如果不想一个的标准输入输出函数出错(例如printf之类),可以将0,1,2描述字指向/dev/null。当然既然是后台守护进程,其实这也没多大必要

 

//后面的代码就见过很多次了

        int sockfd;
        struct sockaddr_in serv_socket;
        char buf[MAXSIZE + 1];

        sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        bzero(&serv_socket, sizeof(serv_socket));
        serv_socket.sin_family = AF_INET;
        serv_socket.sin_addr.s_addr = htonl(INADDR_ANY);
        serv_socket.sin_port = htons(9843);

        int flag = bind(sockfd, (struct sockaddr *)&serv_socket, sizeof(serv_socket));
        if(flag == -1) {
                syslog(LOG_DEBUG | LOG_LOCAL0, "bind error\n");
                exit(1);
        }

        for(;;) {
                struct  sockaddr_in client_socket;
                socklen_t len = sizeof(client_socket);
                int n = recvfrom(sockfd, buf, MAXSIZE, 0, (struct sockaddr *)&client_socket, &len);
                char client_ip[16];
                inet_ntop(AF_INET, &client_socket.sin_addr, client_ip, sizeof(client_ip));
                syslog(LOG_DEBUG | LOG_LOCAL0, "get message from %s\n", client_ip);
                int flag = sendto(sockfd, buf, n, 0, (struct sockaddr *)&client_socket, sizeof(client_socket));
                if(flag == -1)
                        syslog(LOG_DEBUG | LOG_LOCAL0, "send message to %s false\n", client_ip);
        }
}

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics