进程任务通信3种方式

1>socket(套接字通信)

基于TCP服务器实现:

int main()
{
    //1、创建套接字,用于连接使用
    int sfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sfd == -1)
    {
        perror("socket error");
        return -1;
    }
    
    //设置端口号快速重用
    int reuse = 1;
    if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1)
    {
        perror("setsockopt error");
        return -1;
    }
    printf("端口快速重用成功\n");


    //2、给套接字绑定地址信息
    //2.1 填充地址信息结构体
    struct sockaddr_in sin;
    sin.sin_family = AF_INET;    //地址族
    sin.sin_port = htons(PORT);    //端口号网络字节序
    sin.sin_addr.s_addr = inet_addr(IP); //IP地址网络字节序

    //2.2 绑定工作
    if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) == -1)
    {
        perror("bind error");
        return -1;
    }
    printf("bind success _%d_\n", __LINE__);
    

    //3、将套接字设置成监听状态
    if(listen(sfd, 128) == -1)
    {
        perror("listen error");
        return -1;
    }
    printf("listen success _%d_\n", __LINE__);
    

    //4、阻塞等待客户端的连接请求
    //4.1 填充要接收的客户端地址信息结构体
    struct sockaddr_in cin;
    cin.sin_family = AF_INET;   //IPv4通信
    //客户端的主机地址和端口号就无需写了
    //4.2 定义接收客户端的地址信息的大小
    socklen_t socklen = sizeof(cin);

    //4.3 接收客户端的请求
    int newfd = accept(sfd, (struct sockaddr*)&cin, &socklen);
    if(newfd == -1)
    {
        perror("accept error");
        return -1;
    }
    printf("有新客户端连接,newfd = %d\n", newfd);
    
    //5、收发数据
    char buf[128] = "";      //用于接收数据的缓冲区
    while(1)
    {
        //清空缓冲区
        bzero(buf, sizeof(buf));
        int ret = recv(newfd, buf, sizeof(buf), 0);
        if(ret == -1)
        {
            perror("recv error");
            return -1;
        }else if(ret == 0)
        {
            printf("客户端已经下线\n");
            break;
        }

        printf("[%s:%d] :%s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), buf);

        //将数据连接一个字符后发回去
        strcat(buf, "*_*");
        if(send(newfd, buf, sizeof(buf), 0) == -1)
        {
            perror("send error");
            return -1;
        }
    }

    //6、关闭套接字
    close(newfd);           //关闭通信的套接字
    close(sfd);               //关闭连接的套接字

    return 0;
}

基于TCP客户端实现:

int main()
{
    //1、创建套接字,用于连接使用
    int cfd = socket(AF_INET, SOCK_STREAM, 0);
    if(cfd == -1)
    {
        perror("socket error");
        return -1;
    }

    //设置端口号快速重用
    int reuse = 1;
    if(setsockopt(cfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1)
    {
        perror("setsockopt error");
        return -1;
    }
    printf("端口快速重用成功\n");

    //2、给套接字绑定地址信息
    //2.1 填充地址信息结构体
    struct sockaddr_in sin;
    sin.sin_family = AF_INET;    //地址族
    sin.sin_port = htons(PORT);    //端口号网络字节序
    sin.sin_addr.s_addr = inet_addr(IP); //IP地址网络字节序
    
    //2.2 绑定工作
    if(bind(cfd, (struct sockaddr*)&sin, sizeof(sin)) == -1)
    {
        perror("bind error");
        return -1;
    }
    printf("bind success _%d_\n", __LINE__);

    //4、连接服务器
    //4.1 填充要连接的服务器地址信息结构体
    struct sockaddr_in cin;
    cin.sin_family = AF_INET;   //IPv4通信
    cin.sin_port = htons(PORT);    //服务器端口号
    cin.sin_addr.s_addr = inet_addr(IP);      //服务器的主机地址

    //4.2 连接服务器
    if(connect(cfd, (struct sockaddr*)&cin, sizeof(cin)) == -1)
    {
        perror("connect error");
        return -1;
    }
    printf("connect success _%d_\n", __LINE__);

    //5、收发数据
    char buf[128] = "";      //用于接收数据的缓冲区
    while(1)
    {
        //清空缓冲区
        bzero(buf, sizeof(buf));

        //从终端上获取数据
        fgets(buf, sizeof(buf), stdin);
        buf[strlen(buf) -1] = '\0';

        //发送给服务器端
        if(send(cfd, buf, sizeof(buf), 0) == -1)
        {
            perror("send error");
            return -1;
        }
        printf("发送成功\n");

        //接收服务器发来的消息
        bzero(buf, sizeof(buf));
        int res = recv(cfd, buf, sizeof(buf), 0);
        if(res == -1)
        {
            perror("recv error");
            return -1;
        }else if(res == 0)
        {
            printf("服务器已经下线\n");
            break;
        }

        printf("[%s:%d] :%s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), buf);
    
    }

    //6、关闭套接字
    close(cfd);               //关闭连接的套接字

    return 0;
}

2>无名管道

int main()
{
    //定义子进程的pid
    pid_t pid;

    //1、定义管道的文件描述符数组
    int pipefd[2] = {0};
    //2、创建管道
    if(pipe(pipefd) != 0)
    {
        perror("pipe error");
        return -1;
    }

    //创建子进程
    pid = fork();
    if(pid < 0)
    {
        perror("fork error");
        return -1;

    }else if(pid == 0)
    {
        //关闭写管道
        close(pipefd[1]);

        //子进程
        char rbuf[128] = "";

        while(1)
        {
            //清空容器内容
            memset(rbuf, 0, sizeof(rbuf));
            
            //读取父进程发送的消息
            read(pipefd[0], rbuf, sizeof(rbuf));

            printf("收到父进程消息:%s\n", rbuf);
            if(strcmp(rbuf, "quit") == 0)
            {
                break;
            }
        }
        
        //关闭读管道
        close(pipefd[0]);

        //退出进程
        exit(0);


    }else
    {

        //关闭读管道
        close(pipefd[0]);

        //父进程
        char wbuf[128] = "";

        while(1)
        {
            bzero(wbuf, sizeof(wbuf));          //清空容器内容
        //    printf("请输入>>");
            fgets(wbuf, sizeof(wbuf), stdin);          //从终端读取一个字符串
            wbuf[strlen(wbuf)-1] = '\0';                 //将容器中的换行变成'\0'
            
            //将该数据发送给子进程
            //3、向管道文件中写数据
            write(pipefd[1], wbuf, sizeof(wbuf));
            //参数1:要写入的文件描述符
            //参数2:要写入数据的起始地址
            //参数3:要写入数据的大小
            
            if(strcmp(wbuf, "quit") == 0)
            {
                break;
            }
        }

    }

    wait(NULL);            //阻塞回收子进程资源

    //关闭写端
    close(pipefd[1]);

    return 0;
}

3>共享内存

send:

int main()
{
    //1、获取key值
    key_t key;
    if((key = ftok("./", 'k')) == -1)
    {
        perror("ftok error");
        return -1;
    }

    //2、创建共享内存
    int shmid;
    if((shmid = shmget(key, 4096, IPC_CREAT|0664)) == -1)
    {
        perror("shmget error");
        return -1;
    }

    //3、映射内存地址
    char *addr = shmat(shmid, NULL, 0);
    if(addr == (void*)-1)
    {
        perror("shmat error");
        return -1;
    }

    printf("addr = %p\n", addr);           //输出共享内存的地址

    //向共享内存中写数据
    printf("请输入>>:");
    fgets(addr, SIZE, stdin);         //直接从终端获取数据到共享内存中
    addr[strlen(addr) - 1] = 0;

    //4、取消映射
    if(shmdt(addr) == -1)
    {
        perror("shmdt error");
        return -1;
    }

    //5、删除共享内存
    //shmctl(shmid, IPC_RMID, NULL);

    return 0;
}

recv:

int main()
{
    //1、获取key值
    key_t key;
    if((key = ftok("./", 'k')) == -1)
    {
        perror("ftok error");
        return -1;
    }

    //2、创建共享内存
    int shmid;
    if((shmid = shmget(key, 4096, IPC_CREAT|0664)) == -1)
    {
        perror("shmget error");
        return -1;
    }

    //3、映射内存地址
    char *addr = shmat(shmid, NULL, 0);
    if(addr == (void*)-1)
    {
        perror("shmat error");
        return -1;
    }

    printf("addr = %p\n", addr);           //输出共享内存的地址

    //读取共享内存中的内容
    printf("共享内存中的内容:%s\n", addr);

    //4、取消映射
    if(shmdt(addr) == -1)
    {
        perror("shmdt error");
        return -1;
    }

    //5、删除共享内存
    //shmctl(shmid, IPC_RMID, NULL);

    return 0;
}

相关推荐

  1. 进程任务通信3方式

    2024-02-04 17:58:02       59 阅读
  2. linux 进程间几常见通信方式介绍

    2024-02-04 17:58:02       59 阅读
  3. 进程通信方式

    2024-02-04 17:58:02       55 阅读
  4. Android中使用USB进行通信的4方式

    2024-02-04 17:58:02       34 阅读
  5. MySQL客户端和服务器进程通信的几方式

    2024-02-04 17:58:02       39 阅读
  6. FreeRTOS的任务通信方式

    2024-02-04 17:58:02       42 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-04 17:58:02       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-04 17:58:02       106 阅读
  3. 在Django里面运行非项目文件

    2024-02-04 17:58:02       87 阅读
  4. Python语言-面向对象

    2024-02-04 17:58:02       96 阅读

热门阅读

  1. 开源计算机视觉库OpenCV详解和实际运用案例

    2024-02-04 17:58:02       52 阅读
  2. windows下docker的使用

    2024-02-04 17:58:02       50 阅读
  3. 如何选择Centos的替代者

    2024-02-04 17:58:02       48 阅读
  4. docker内的资源隔离的linux实现

    2024-02-04 17:58:02       50 阅读
  5. Docker 常用命令详细介绍

    2024-02-04 17:58:02       48 阅读
  6. LeetCode 每日一题 2024/1/29-2024/2/4

    2024-02-04 17:58:02       47 阅读
  7. C#面:简述什么叫应用程序域

    2024-02-04 17:58:02       51 阅读
  8. 蓝桥杯经典 年号字串

    2024-02-04 17:58:02       49 阅读