Linux网络-守护进程版字典翻译服务器

文章目录


前言

根据上章所讲的后台进程组和session会话,我们知道如果可以将一个进程放入一个独立的session,可以一定程度上守护该进程。


一、pid_t setsid(void);

该系统接口函数可以将一个不是进程组组长的进程放入一个独立的session会话的后台进程中。

二、守护进程

cpp 复制代码
#include <signal.h>
#include <unistd.h>
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

const std::string filepath = "/dev/null";
void Daemon(const std::string &cwd = "")
{
    // 1.忽略非致命终止信号
    signal(SIGCHLD, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);
    signal(SIGSTOP, SIG_IGN);


    // 2.fork并进入独立session
    if (fork() > 0)
        exit(0);
    setsid();


    // 3.改变工作目录
    if (!cwd.empty())
        chdir(cwd.c_str());


    // 4.标准输入输出错误文件描述符重定向
    int fd = open(filepath.c_str(), O_RDWR);
    if (fd != -1)
    {
        dup2(fd, 0);
        dup2(fd, 1);
        dup2(fd, 2);
        close(fd);
    }

}
  1. 忽略掉忽略非致命终止信号,使进程不那么容易被信号终止。
  2. 因为setsid接口函数我们说过,它不能把一个是进程组组长的进程放入一个独立的session会话当中,既然不能是进程组组长,那我们就创建一个子进程来运行后续代码,父进程直接退出。
  3. 在有一定需求的情况下,可以更改自己的工作目录。
  4. 因为放入到独立的session会话中,向标准输入输出错误读写操作就没有意义了,所以我们可以重定向标准输入输出错误文件描述符。 而Linux系统给我们提供了这么一个文件在/dev/null,它是Linux系统专门提供给用户存放垃圾数据的文件,我们不管向里面怎么写数据,该文件大小保持不变;不管怎么读都是空。

翻译字典服务器(守护线程版)

cpp 复制代码
#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <string>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include "log.hpp"
#include <netinet/in.h>
#include <string.h>
#include <pthread.h>
#include "threadPool.hpp"
#include "Task.hpp"
#include <signal.h>
#include "daemon.hpp"

const std::string default_ip = "0.0.0.0";
const uint16_t default_port = 8888;
const int backlog = 10;

std::string messageHandle(const std::string &ip, uint16_t port, const std::string &message)
{
    time_t now = time(nullptr);
    struct tm *lt = localtime(&now);
    std::cout << lt->tm_hour << ":" << lt->tm_min << "[" << ip << ":" << port << "]: "
              << message << std::endl;
    return message;
}
class TcpServer;

class TcpServer
{
public:
    TcpServer(const uint16_t& port = default_port, const std::string& ip = default_ip)
        : _listensock(-1)
        , _server_ip(ip)
        , _server_port(port)
    {
    }

    void Init()
    {
        Daemon();
        // 申请套接字
        int sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock == -1)
        {
            lg(Fatal, "socket create failed...");
            exit(1);
        }
        lg(Debug, "socket create succeess...");

        _listensock = sock;

        // bind套接字
        struct sockaddr_in local;
        memset(&local, 0, sizeof local);
        local.sin_family = AF_INET;
        inet_aton(_server_ip.c_str(), &local.sin_addr);
        local.sin_port = htons(_server_port);
        if (bind(_listensock, (const sockaddr *)&local, (socklen_t)sizeof(local)) == -1)
        {
           lg(Fatal, "bind failed..., error:%s", strerror(errno));
            exit(2);
        }
        lg(Debug, "bind succeess...");

        // listen begin
        if (listen(_listensock, backlog) < 0)
        {
            lg(Fatal, "listen failed...");
            exit(3);
        }
        lg(Debug, "listen succeess...");
    }

    void run()
    {
        signal(SIGPIPE, SIG_IGN); // 防止因为读端关闭导致整个进程直接退出
        struct sockaddr_in client;
        socklen_t len;
        ThreadPool<Task>::GetInstance()->Start();
        while (true)
        {
            memset(&client, 0, sizeof client);
            int socketfd = accept(_listensock, (struct sockaddr *)&client, &len);
            if (socketfd < 0)
            {
                lg(Warning, "accept failed...");
                continue;
            }
            lg(Info, "accept success..., and get a link, socketfd: %d", socketfd);
            ThreadPool<Task> *threadpool = ThreadPool<Task>::GetInstance();
            threadpool->Push(Task(socketfd, client));
        }
    }

private:
    int _listensock;
    std::string _server_ip;
    uint16_t _server_port;
};

效果图

相关推荐
郝亚军9 分钟前
ubuntu-18.04.6-desktop-amd64安装步骤
linux·运维·ubuntu
Konwledging29 分钟前
kernel-devel_kernel-headers_libmodules
linux
Web极客码30 分钟前
CentOS 7.x如何快速升级到CentOS 7.9
linux·运维·centos
一位赵1 小时前
小练2 选择题
linux·运维·windows
代码游侠1 小时前
学习笔记——Linux字符设备驱动开发
linux·arm开发·驱动开发·单片机·嵌入式硬件·学习·算法
LucDelton2 小时前
Java 读取无限量文件读取的思路
java·运维·网络
Lw老王要学习2 小时前
CentOS 7.9达梦数据库安装全流程解析
linux·运维·数据库·centos·达梦
Kaede62 小时前
提示dns服务器未响应,需要做哪些事?
运维·服务器
CRUD酱2 小时前
CentOS的yum仓库失效问题解决(换镜像源)
linux·运维·服务器·centos
Wasim4042 小时前
【渗透测试】SQL注入
网络·数据库·sql