Unix 域套接字 (C++) - 客户端崩溃服务器守护进程

Posted

技术标签:

【中文标题】Unix 域套接字 (C++) - 客户端崩溃服务器守护进程【英文标题】:Unix Domain Socket (C++) - Client crashes server daemon 【发布时间】:2015-07-02 15:51:09 【问题描述】:

我遇到了很大的问题。 我最近开始研究守护进程和套接字编程。我当前的设置由一个创建套接字的守护进程和一个写入消息并读取处理后的答案的客户端组成。 那么,应该阅读答案。

守护进程自己守护进程,创建套接字,甚至处理消息(我可以通过我创建的日志条目进行验证),但是一旦我尝试将答案发送给客户端,守护进程就会被阻止;客户端永远不会收到答案,如果我 ctrl-c 客户端,守护进程也会关闭。 这对我来说是完全奇怪的行为,我无法解释发生了什么,这就是为什么我要问你任何提示。

简要总结: - 套接字类型是AF_UNIX,因此是本地的,不涉及网络 - 守护进程成功接收消息,但无法回写 - 客户端无法读取(因为服务器的send() 阻塞)和 如果我ctrl-c 客户端守护进程也退出(但该信号不会发送到守护进程)

以下是我的代码,精简到有趣且不起作用的部分。 非常感谢您的提示、帮助和建议!

更新:

也添加了客户端代码!

int main()

    //those two work just fine
    createSocket();
    daemonize();

    //declare some variables needed in the big loop
    FILE *client_fd;
    int fd;
    socklen_t len;
    string tmp;
    char *buf = new char[1024];
    while(1)
    
        struct sockaddr_un saun;
        len = sizeof(saun);

        //receive an fd for the incoming connection
        if((fd = accept(m_socket, (sockaddr*)&saun, &len)) < 0)
        
            writeLog("Accepting connection failed!");
            continue;
        
        //i wanted to use fgets, therefore obtain a FILE object here
        client_fd = fdopen(fd, "r");
        if(client_fd == NULL)
        
            writeLog("fdopen() failed!");
            continue;
        
        while(fgets(buf, bufferSize, client_fd) != NULL)
        
            //message read succeeds (verified)
            writeLog(buf);
            tmp = evaluateMsg(buf);

            //tmp is not empty (verified)
            writeLog(tmp);

            //send seems to block, nothing happens from now on
            //I don't even get in one of the if-else branches
            if(send(fd, (tmp + "\n").c_str(), tmp.size() + 1, 0) < 0)
            
                writeLog("Could not write message back!");
                continue;
            
            else
                writeLog("bytes written!");
        
        close(fd);
    

以下是客户端代码:

int main()

    int sockfd;
    sockaddr_un addr;

    sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
    addr.sun_family = AF_UNIX;
    strcpy(addr.sun_path, SOCKET_PATH);

    //the connection is successfull
    if(connect(sockfd, (sockaddr*)&addr, sizeof(addr)) < 0)
    
        cerr<<"Connection failed!"<<endl;
        exit(1);
    
    //message is written successfully
    write(sockfd, "hello", 5);
    char *buf = new char[1024];

    //same as for the server, I wanted to use fgets
    //therefore need to obtain a FILE object
    FILE *fd = fdopen(sockfd, "r");
    fgets(buf, 1024, fd);
    cout<<buf<<endl;

    close(sockfd);

【问题讨论】:

能否也给我们看一下客户端代码。看起来客户端实际上没有从套接字读取数据,阻塞了服务器。 当然,抱歉我忘记了... 嗨,Mäx,我们不会在这里回答问题。 (也不要在标题中添加“已解决”之类的标签。)您应该发布您的答案/解决方案作为您问题的答案。谢谢。 哦,对不起,会的! 【参考方案1】:

好的,我自己找到了解决方案。

问题是对fgets() 的(方便)调用;我不得不使用read(),现在一切都像魅力一样。 我不确定为什么read() 是强制性的,但我认为它与缓冲区有关,只要读取它就被清空... 但这只是我的假设!

【讨论】:

以上是关于Unix 域套接字 (C++) - 客户端崩溃服务器守护进程的主要内容,如果未能解决你的问题,请参考以下文章

应用程序崩溃时未删除 Unix 域套接字文件

UNIX域套接字

通过 Unix 域套接字发送结构

UNIX域协议(命名套接字)

C++ UNIX 帮助 - 简单的 TCP 服务器套接字连接

如何使用 SOCK_DGRAM 制作双向 unix 域套接字?