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;
}
相关推荐
aqymnkstkw28 分钟前
2024年【电气试验】考试题库及电气试验模拟试题
大数据·c语言·人工智能·嵌入式硬件·安全
qmx_0732 分钟前
MFC-基础架构
c++·mfc
万象.34 分钟前
STL_vector实现及干货以及vector迭代器失效问题
c++
想变成自大狂35 分钟前
C++中的异构容器
开发语言·c++
小米里的大麦38 分钟前
【C++】深入理解引用:从基础到进阶详解
c++·经验分享·笔记·引用·引用和指针
float_com1 小时前
【STL】stack,deque,queue 基础,应用与操作
c++·stl·极速入门
学习使我变快乐1 小时前
C++:用类实现链表,队列,栈
开发语言·c++·链表
lmy_t1 小时前
C++之第十二课
开发语言·c++
马剑威(威哥爱编程)2 小时前
除了递归算法,要如何优化实现文件搜索功能
java·开发语言·算法·递归算法·威哥爱编程·memoization
算法萌新——12 小时前
洛谷P2240——贪心算法
算法·贪心算法