0725,进程间传递文件描述符,socketpair + sendmsg/recvmsg

我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了我要碎掉了

上课喵:

pipe匿名管道的问题

cpp 复制代码
#include <func.h>

int main()
{
    int fds[2];
    pipe(fds);
    pid_t pid=fork();
    if(pid>0){ //father
        close(fds[0]);//close read
        int fd=open("file2.txt",O_RDONLY);
        printf("father: fds[1]:%d\n",fds[1]);
        write(fds[1],&fd,sizeof(fd));
        wait(NULL);
        close(fd);
    }else{   //son
        close(fds[1]);//close er
        int chilfd=-1;
        read(fds[0],&chilfd,sizeof(chilfd));  //read baba pipe
        printf("chilefd %d.fds [0]:%d\n",chilfd,fds[0]);

        char buff[100]={0};
        read(chilfd,buff,sizeof(buff));
        printf("buff  %s.\n",buff);
    }
    return 0;
}

writev

cpp 复制代码
#include <func.h>
#include <sys/uio.h>

int main()
{
    char buff[]="love";
    char buff2[]="xixi";
    
    int fd=open("file2.txt",O_RDWR|O_CREAT,0664);
    if(fd==-1){};
    
    struct iovec iov[2];
    iov[0].iov_base=buff;
    iov[0].iov_len=strlen(buff);
    iov[1].iov_base=buff2;
    iov[1].iov_len=strlen(buff2);

    int ret=writev(fd,iov,2);
    printf("ret :%d \n",ret);
    close(fd);
    return 0;
}

readv

cpp 复制代码
#include <func.h>
#include <sys/uio.h>

int main()
{
    char buff[6]={0};
    char buff2[6]={0};
    
    int fd=open("file2.txt",O_RDWR);
    if(fd==-1){};
    
    struct iovec iov[2];
    iov[0].iov_base=buff;
    /* iov[0].iov_len=strlen(buff); */
    iov[0].iov_len=sizeof(buff);
    iov[1].iov_base=buff2;
    iov[1].iov_len=sizeof(buff2);

    int ret=readv(fd,iov,2);
    printf("ret :%d \n",ret);
    printf("buff:%s \n",buff);
    printf("buff2:%s \n",buff2);

    close(fd);
    return 0;
}

结构体struct msghdr的发送和接收实现

真是酣畅淋漓的CP

代码改好了!!

./wr33: sendmsg: Bad file descriptor

嘿嘿~~~因为没有文件所以打开失败了!!!聪明小辉

cpp 复制代码
#include <func.h>
#include <sys/uio.h>


int sendFd(int pipefd,int fd){
    //buid 2 group
    char buff[6]="hellp";
    struct iovec iov;
    memset(&iov,0,sizeof(iov));
    iov.iov_base=buff;
    iov.iov_len=sizeof(buff);

    //build 3 group
    int len=CMSG_LEN(sizeof(fd));
    struct cmsghdr* cmsg=(struct cmsghdr*)calloc(1,len);
    cmsg->cmsg_len=len;
    cmsg->cmsg_level=SOL_SOCKET;
    cmsg->cmsg_type=SCM_RIGHTS;
    int * p=(int*)CMSG_DATA(cmsg);
    *p=fd;
    
    // buid msghdr
    struct msghdr msg;
    memset(&msg,0,sizeof(msg));
    msg.msg_iov=&iov;
    msg.msg_iovlen=1;
    msg.msg_control=cmsg;//传递文件描述
    msg.msg_controllen=len;

    int ret=sendmsg(pipefd,&msg,0);
    printf("sendmsg ret: %d\n",ret);
    if(ret==-1){error(1,errno,"sendmsg");}
    free(cmsg);
    return 0;
}

int recvFd(int pipefd,int *pfd){

    //buid 2 group
    char buff[6]={0};
    struct iovec iov;
    memset(&iov,0,sizeof(iov));
    iov.iov_base=buff;
    iov.iov_len=sizeof(buff);

    //3 group
    int len=CMSG_LEN(sizeof(int));
    struct cmsghdr* cmsg=(struct cmsghdr*)calloc(1,len);
    cmsg->cmsg_len=len;
    cmsg->cmsg_level=SOL_SOCKET;
    cmsg->cmsg_type=SCM_RIGHTS;

    struct msghdr msg;
    memset(&msg,0,sizeof(msg));
    msg.msg_iov=&iov;
    msg.msg_iovlen=1;
    msg.msg_control=cmsg;//传递文件描述符
    msg.msg_controllen=len;

    int ret =recvmsg(pipefd,&msg,0);
    if(ret==-1){error(1,errno,"recvmsg");}
    int* p=(int*)CMSG_DATA(cmsg);
    printf("buff: %s\n",buff);
    *pfd=*p;//传给外籍的指针(读取文件描述符的值)
    return 0;
}

int main()
{
    int fds[2];
    socketpair(AF_LOCAL,SOCK_STREAM,0,fds);
    pid_t pid=fork();
    if(pid>0){ //father
        close(fds[0]);//close read
        int fd=open("file1.txt",O_RDONLY);
        printf("father fd:%d\n",fd);
        /* write(fds[1],&fd,sizeof(fd)); */
        sendFd(fds[1],fd);
        wait(NULL);
        close(fd);
    }else{   //son
        close(fds[1]);//close er
        int chilfd=-1;
        /* read(fds[0],&chilfd,sizeof(chilfd));  //read baba pipe */
        recvFd(fds[0],&chilfd);
        printf("chilefd %d.fds [0]:%d\n",chilfd,fds[0]);

        char buff[100]={0};
        read(chilfd,buff,sizeof(buff));
        printf("buff  %s.\n",buff);
    }

    return 0;
}

进程池框架的搭建

作业:

01:参考我们上课的代码: 让子进程A打开一个文件, 把这个文件描述符信息发给父进程B, 让父进程B在这个文件上能写一个字符串.

好像没什么用??????

cpp 复制代码
#include <func.h>
#include <sys/uio.h>


int sendFd(int pipefd,int fd){
    //buid 2 group
    char buff[6]={0};
    struct iovec iov;
    memset(&iov,0,sizeof(iov));
    iov.iov_base=buff;
    iov.iov_len=sizeof(buff);

    //build 3 group
    int len=CMSG_LEN(sizeof(fd));
    struct cmsghdr* cmsg=(struct cmsghdr*)calloc(1,len);
    cmsg->cmsg_len=len;
    cmsg->cmsg_level=SOL_SOCKET;
    cmsg->cmsg_type=SCM_RIGHTS;
    int * p=(int*)CMSG_DATA(cmsg);
    *p=fd;
    
    // buid msghdr
    struct msghdr msg;
    memset(&msg,0,sizeof(msg));
    msg.msg_iov=&iov;
    msg.msg_iovlen=1;
    msg.msg_control=cmsg;//传递文件描述
    msg.msg_controllen=len;

    int ret=sendmsg(pipefd,&msg,0);
    if(ret==-1){error(1,errno,"sendmsg");}
    free(cmsg);
    return 0;
}

int recvFd(int pipefd,int *pfd){

    //buid 2 group
    char buff[6]={0};
    struct iovec iov;
    memset(&iov,0,sizeof(iov));
    iov.iov_base=buff;
    iov.iov_len=sizeof(buff);

    //3 group
    int len=CMSG_LEN(sizeof(int));
    struct cmsghdr* cmsg=(struct cmsghdr*)calloc(1,len);
    cmsg->cmsg_len=len;
    cmsg->cmsg_level=SOL_SOCKET;
    cmsg->cmsg_type=SCM_RIGHTS;

    struct msghdr msg;
    memset(&msg,0,sizeof(msg));
    msg.msg_iov=&iov;
    msg.msg_iovlen=1;
    msg.msg_control=cmsg;//传递文件描述符
    msg.msg_controllen=len;

    int ret =recvmsg(pipefd,&msg,0);
    if(ret==-1){error(1,errno,"recvmsg");}
    int* p=(int*)CMSG_DATA(cmsg);
    *pfd=*p;//传给外籍的指针(读取文件描述符的值)
    return 0;
}

int main()
{
    int fd[2];
    int err=socketpair(AF_LOCAL,SOCK_STREAM,0,fd);
    if(err==-1){error(1,errno,"sockpair");}

    int pid=fork();
    switch (pid){
    case -1:
        error(1,errno,"fork");break;
    case 0:
        {
        close(fd[0]);
        printf("child process:%d\n",getpid());
        int pfd;
        recvFd(fd[1],&pfd);
        char buff[]="我恨你我恨你我恨你!!!!!\n";
        write(pfd,buff,sizeof(buff));
        close(pfd);
        break;
        }
    default:
        {
        close(fd[1]);
        int filefd=open("file2.txt",O_RDWR);
        if(filefd==-1){error(1,errno,"open");}
        sendFd(fd[0],filefd);
        break;
        }      
    }
    return 0;
}

所以那狗东西要怎么打印出来可恶!!!!

02:仿照我们上课写的进程池, 自己手写(不要直接复制)一个进程池代码。

抄抄抄:

02:使用select编写聊天室程序:客户端和服务端使用tcp通信;服务端可以处理新客户端的连接和转发消息;客户端可以连入服务端并发送消息。

哥们发现少一个右括号直接傻眼了喵
cpp 复制代码
xiaohuichen@xiaohuichen-virtual-machine:~/001/724$ cat douqusi.c
#include <func.h>
#define IP1  "192.168.235.128"
#define PORT1 8080

int main()
{
    struct sockaddr_in addr;
    addr.sin_family=AF_INET;
    addr.sin_port=htons(PORT1);
    addr.sin_addr.s_addr=inet_addr(IP1);

    int lifd=socket(AF_INET,SOCK_STREAM,0);
    bind(lifd,(struct sockaddr *)&addr,sizeof(struct sockaddr));
    listen(lifd,100);
    
    int ac_fd[1000];
    int ac_num=0;
    char buf[256];
    char buf_sent[256];

    fd_set readfds;
    FD_ZERO(&readfds);
    int fd_max;

    FD_SET(lifd,&readfds);
    fd_max=lifd;

    fd_set old_fds=readfds;
    printf("listenning\n");

    while(1){
        readfds=old_fds;
        select (fd_max+1,&readfds,NULL,NULL,NULL);
        if(FD_ISSET(lifd,&readfds)){
            ac_fd[ac_num]=accept(lifd,NULL,NULL);
            FD_SET(ac_fd[ac_num],&old_fds);
            if(ac_fd[ac_num]>fd_max){
                fd_max=ac_fd[ac_num];
            }
            ac_num++;
            printf("welcome user%d \n",ac_fd[ac_num-1]);
        }

        for(int i=0;i<ac_num;i++){
            if(FD_ISSET(ac_fd[i],&readfds)){
                int a=recv(ac_fd[i],buf,256,0);
                if(a==0){close(ac_fd[i]);}
            }
            sprintf(buf_sent,"user%d:%s",ac_fd[i],buf);
            for(int j=0;j<ac_num;j++){
                send(ac_fd[j],buf_sent,strlen(buf_sent)+1,0);
            }
        }
    }
    return 0;
}

HTTP:(咳咳,是我不知道怎么跑然后连了一个客户端喵)

cpp 复制代码
#include <func.h>
#define IP1  "192.168.235.128"
#define PORT1 8080

struct sockaddr* addr_create(const char* ip,int  port ){

    struct sockaddr_in* addr=(struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));
    memset(addr,0,sizeof(*addr));
    addr->sin_family=AF_INET;
    addr->sin_port=htons(port);
    addr->sin_addr.s_addr=inet_addr(ip);
    return (struct sockaddr*)addr;
}

int main()
{
    int sofd=socket(AF_INET,SOCK_STREAM,0);
    if(sofd==-1){error(1,errno,"socket");}

    int on=1;
    int ret=setsockopt(sofd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
    if(ret==-1){error(1,errno,"setsoclopt");}
    
    struct sockaddr* addr=addr_create(IP1,PORT1);
    ret=bind(sofd,addr,sizeof(*addr));
    if(ret==-1){error(1,errno,"bind");}
    
    ret=listen(sofd,1);

    while(1){
        int peerfd=accept(sofd,NULL,NULL);
        char buff[4096]={0};
        
        ret=recv(peerfd,buff,sizeof(buff),0);
        printf("\nrecv: %d.bytes \n",ret);
        printf("----%s\n",buff);

        char response[4096]={0};
        const char* start_line="HTTP/1.1 200 ok\r\n";
        const char* headers="Server:MyHttpServer1.0\r\n"
            "Connection:keep-aliave\r\n"
            "Conntent-Type:text/html\r\n"
            "Content-Length:";
        const char* empty_line="\r\n";
        const char* body="<html><head>This is a test</head><body>hello,client</body></html>";
        sprintf(response,"%s%s%ld\r\n%s%s",
                start_line,
                headers,
                strlen(body),
                empty_line,
                body);
        send(peerfd,response,strlen(response),0);

    }

    close(sofd);
    return 0;
}
相关推荐
CSCN新手听安1 小时前
list的常用操作
数据结构·list
编程之路,妙趣横生1 小时前
list模拟实现
c++
梅茜Mercy3 小时前
数据结构:链表(经典算法例题)详解
数据结构·链表
88号技师3 小时前
2024年12月一区SCI-加权平均优化算法Weighted average algorithm-附Matlab免费代码
人工智能·算法·matlab·优化算法
IT猿手3 小时前
多目标应用(一):多目标麋鹿优化算法(MOEHO)求解10个工程应用,提供完整MATLAB代码
开发语言·人工智能·算法·机器学习·matlab
青春男大3 小时前
java栈--数据结构
java·开发语言·数据结构·学习·eclipse
88号技师3 小时前
几款性能优秀的差分进化算法DE(SaDE、JADE,SHADE,LSHADE、LSHADE_SPACMA、LSHADE_EpSin)-附Matlab免费代码
开发语言·人工智能·算法·matlab·优化算法
Zer0_on3 小时前
数据结构栈和队列
c语言·开发语言·数据结构
一只小bit3 小时前
数据结构之栈,队列,树
c语言·开发语言·数据结构·c++
马浩同学4 小时前
【GD32】从零开始学GD32单片机 | DAC数模转换器 + 三角波输出例程
c语言·单片机·嵌入式硬件·mcu