QT按钮socket远程控制opengl模型(4)--Apple的学习笔记

QT按钮socket远程控制opengl模型(3)验证功能通过后,
Linux Server端采用进程IPC通信
。子进程为opengl的显示。比起多线程,多进程需要处理下进程同步关闭及僵尸进程。代码工程依然更新到我的码云

一,进程设计

进程IPC通信.png

二,遇到的问题

1.vscode无法调试多进程

解决方案:
launch.json添加:
"setupCommands": [
{"text": "-gdb-set follow-fork-mode child"}
]

2.linux消息队列msgrcv收不到消息的问题

解决方案:没有用man来仔细看msgrcv的函数,网上直接搜索了下,就找到了答案。msgrcv的第一个对象需要使用long,之前32位机上我用int测试通过,现在机器为64bit系统,所以long和int的字节数量就不是4字节了,64bit机器的long为8个字节,所以msgrcv一直无法接收到数据。修改传入参数的结构第一个对象为long型,验证通过。

2.比起多线程,需要关注同步2个进程的退出

由于Linux Server端窗口关闭后,主进程socket依然在和win10的client通信。所以opengl窗口关闭后,需要让server进程也关闭。
查了资料,其实进程间算是平等的。
僵尸进程就是指:一个进程执行了exit系统调用退出,而其父进程并没有为它收尸(调用wait或waitpid来获得它的结束状态)的进程。
任何一个子进程(init除外)在exit后并非马上就消失,而是留下一个称外僵尸进程的数据结构,等待父进程处理。这是每个子进程都必需经历的阶段。另外子进程退出的时候会向其父进程发送一个SIGCHLD信号。

进程间保活方案可以通过消息互发,若检测到子进程不发消息给父进程,则可以关闭子进程,再关闭父进程。
解决方案:由于我是socket读写,有阻塞,所以我通过在SIGCHLD通知函数中直接调用exit(0)进行强制退出。

三,main.cpp代码

#include "socket.h"
#include "showgl.h"
#include "ipc.h"

void handler(int sig)
{
    pid_t pid;
    while((pid=waitpid(-1,NULL,WNOHANG))>0)
    {
        printf("wait child is sucessful\n");
        exit(0); //kill father pid
    }
    printf("child is quit\n");
}

int main(int argc, char **argv)
{
    int ret = E_NOK;
    int keydata = 0;
    signal(SIGCHLD,handler);
    /* server operations */
    baseServer *pServer = new baseServer();
    pServer->socketCreate(AF_INET, SOCKET_TYPE, INADDR_ANY, PORT_ID, baseSocket::E_SERVER);
    pServer->socketBind();
    pServer->socketListen(2);
    MYmsg * pMymsg = new MYmsg();
    pMymsg->CreateMsg();
    /* task process */
    ServerHandler *pServerTask = new ServerHandler(pMymsg);
    /* create task for socket to send heartbeat */
    std::thread taskSendHeart(&ServerHandler::sendHeart, pServerTask, pServer);

    
/* create task for opengl to display 3D */
#if (USEFORK == true)
    pid_t id = fork();
    std::cout << "pid=" << id << std::endl;

    if (id < 0)
    {
        std::cout << "fork error" << std::endl;
        exit(0);
    }
    else if (id == 0) //child read
    {
        ShowOpengl *pShowTask = new ShowOpengl();
        pShowTask->glHandler(pMymsg);
        delete pShowTask;
        exit(0);
    }
    else
#else
    ShowOpengl *pShowTask = new ShowOpengl();
    std::thread taskOpengl(&ShowOpengl::glHandler, pShowTask, pServerTask);
#endif
    {//father
        std::cout << "start server\n"; // for debug code
        while (1)
        {
            /* wait client signal to connect */
            ret = pServer->socketAccept();
            std::cout << "h\n"; // for debug code

            /* create task for socket to receive key command */
            std::thread taskRec(&ServerHandler::readinfo, pServerTask, pServer);
            taskRec.detach();

            if (ret == E_OK)
            {
                std::cout << "connect success" << std::endl;
            }
        }
    }
    /* close socket */
    pServer->socketDisconnect(pServer->getConnectfd());
    taskSendHeart.join();
#if (USEFORK == true)
#else
    taskOpengl.join();
    delete pShowTask;
#endif
    delete pServerTask;
    delete pServer;
    pMymsg->delMsg();
    delete pMymsg;
}

你可能感兴趣的:(QT按钮socket远程控制opengl模型(4)--Apple的学习笔记)