Qt下使用fork创建进程并使用socket通信

 

 

把最近工作总结下。

之前在嵌入python解释器的过程中,我们没有处理这样一种情况:当Python解释器正在执行一个阻塞操作(比如socket server 在监听一个客户端连入),这时我们需要终止解释器的运行,该如何操作呢?

在Qt线程中不容易实现该功能,如果在socket 监听时终止python解释器,那么再次运行时端口就会显示被占用,因为资源没有清理。为了解决这种情况,我们让解释器运行在一个进程中。这样在需要停止时,我们可以发送kill信号终止进程。

老规矩,接下来上码:

 

#include "mainwindow.h"

#include "ui_mainwindow.h"

#include <QThread>

#include <QDebug>

#include <signal.h>

#include <sys/types.h>

#include <unistd.h>    //close head file

#include <sys/wait.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

 

int childProcessId = -1;

int client_sockfd;

 

 

void sigint(int);

 

void sigint(int signal)

{

    if(SIGINT == signal)

    {

        qDebug() << "My DADDY has Killed me!!!";

        exit(0);

    }

 

}

MainWindow::MainWindow(QWidget *parent) :

    QMainWindow(parent),

    ui(new Ui::MainWindow)

{

    ui->setupUi(this);

 

    //tcp server

    processServer = new QTcpServer();

    connect(processServer, SIGNAL(newConnection()),

            this, SLOT(slot_recvClientConnect()));

    if(!processServer->listen(QHostAddress::Any, 8866))

    {

        //监听本地主机的8866端口,如果出错就输出错误信息,并关闭

        qDebug() <<"error message"<<processServer->errorString();

        processServer->close();

    }

 

    ///client

    struct sockaddr_in remote_addr; //服务器端网络地址结构体

    memset(&remote_addr,0,sizeof(remote_addr)); //数据初始化--清零

    remote_addr.sin_family=AF_INET; //设置为IP通信

    remote_addr.sin_addr.s_addr=inet_addr("127.0.0.1");//服务器IP地址

    remote_addr.sin_port=htons(8866); //服务器端口号

 

    /*创建客户端套接字--IPv4协议,面向连接通信,TCP协议*/

    if((client_sockfd=socket(PF_INET,SOCK_STREAM,0))<0)

    {

        perror("socket");

        return;

    }

 

    /*将套接字绑定到服务器的网络地址上*/

    if(::connect(client_sockfd,(struct sockaddr *)&remote_addr,sizeof(struct sockaddr))<0)

    {

        perror("connect");

        return;

    }

 

}

 

MainWindow::~MainWindow()

{

    processServer->close();

    delete ui;

    delete processServer;

}

 

 

void MainWindow::slot_recvClientConnect()

{

    qDebug() << "accept connect";

 

    clientConnect = processServer->nextPendingConnection();

    connect(clientConnect, SIGNAL(readyRead()),

            this, SLOT(slot_readClientData()));

}

 

void MainWindow::slot_readClientData()

{

    QString str;

    str = clientConnect->readAll();

 

    clientConnect->write("hello");

 

 

    qDebug() << "client data>>:" << str  ;

}

 

 

void MainWindow::on_pbn_start_clicked()

{

    pid_t pid;

    pid = fork();

 

    if(pid < 0)

    {

        qDebug() << "creat process faild!";

    }

    else if((pid_t)0 == pid)  //child process,pid is child pid

    {

        signal(SIGINT, sigint);

 

        qDebug() << "this is client proccess!";

 

        char buf1[] = "socket client";

        while(1)

        {

            send(client_sockfd,buf1,strlen(buf1),0);

            QThread::sleep(3);

        }

    }

    else                  // parent process

    {

        childProcessId = pid;

        qDebug() << "child process pid is " << childProcessId;

    }

 

}

 

void MainWindow::on_pbn_stop_clicked()

{

    if(-1 != childProcessId)

    {

        pid_t pidClear;

 

        kill(childProcessId, SIGINT);

        QThread::usleep(500);

 

        do{

            pidClear = waitpid(childProcessId,NULL,WNOHANG);

            if(-1 == pidClear)

            {

                qDebug() << "clear  error!!!";

            }

 

            if(childProcessId == pidClear)

            {

                qDebug() << "clear   success!!!";

            }

            QThread::usleep(500);

        }while(0 == pidClear);

        childProcessId = -1;

    }

 

}

 

程序环境是ubuntu + Qt。

简单介绍下程序的主体构成:构造函数中使用c创建客户端,使用Qt的类创建服务器。

界面点击start按钮时,使用fork创建子进程,在进程中客户端向服务器发送数据。点击stop按钮时,父进程向子进程发出kill信号,由于子进程注册了中断信号,所以会执行信号函数中的操作。之后父进程使用 waitpid(childProcessId,NULL,WNOHANG)等待清理子进程,之后进程资源被释放。如果python解释器运行在进程中,那么python解释器也会被中断,资源被清理故而不会被占用。Python重定向信息输出也可通过socket发送出来。

 

程序运行效果:

 

在子进程被中断前,先进入信号函数。之后由父进程清理子进程资源。

 

如果大家觉得还阔以,欢迎大家关注公众号

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值