zoukankan      html  css  js  c++  java
  • linux高级编程day08 笔记

    一.基于文件的通信
      1.普通文件(io/mmap)
      2.有名管道文件
      3.匿名管道
      4.Socket

    二.基于内存的通信
      0.一组内核内存的工具
        ipcs 
        ipcs -m
        ipcs -q
        ipcs -s      
        ipcrm -q 编号ID
      1.普通的父子进程之间的匿名内存共享映射
      2.内核共享内存
       编程模型
         2.1.创建共享内存,得到一个ID  shmget
         2.2.把ID影射成虚拟地址(挂载)  shmat
         2.3.使用虚拟地址访问内核共享内存 使用任何内存函数与运算符号            
         2.4.卸载虚拟地址 shmdt
         2.5.删除共享内存 shctl(修改/获取共享内存的属性)
         
       共享内存的属性  
         
    案例:
       A.创建共享内存,并且修改内存数据。
       1.创建共享内存

        int shmget(key_t key,//为什么需要key
                             int size,//共享内存大小
                             int flags//共享内存的属性与权限
                )

          为什么要key_t:
            约定创建与访问的是同一个共享内存。
          第三个参数:
             方式|权限
             方式:创建 IPC_CREAT  IPC_EXCL
             打开:0
            常见的两种方式:
              创建:IPC_CREAT|IPC_EXCL | 0666;
              打开:0
               
         返回:
           成功返回共享内存ID
           失败返回-1   
       B.根据ID得到共享,并且访问内存数据。

        void shmat(int id,
                void *startaddr,//0:系统指定首地址
                int flags)//挂载方式,建议0,可以使用IPC_RDONLY

       C.删除

        int shmctl(int id,//被操作的共享内存ID
                int how,//操作方式:一共三种操作
                struct shmid_ds*ds)//共享内存属性

         how:
           IPC_STAT
           IPC_SET
           IPC_RMID

    View Code
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <signal.h>
    #include <sys/shm.h>
    #include <sys/ipc.h>
    key_t key;
    int shmid;
    int *p;
    int i=0;
    void deal(int s)
    {
        if(s==SIGINT)
        {
            //4.卸载共享内存shmdt
            shmdt(p);
            //5.删除共享内存shctl
            shmctl(shmid,IPC_RMID,0);
            exit(0);
        }
    }
    main()
    {
        
        signal(SIGINT,deal);
        //1.创建共享内存shmget
        key=ftok(".",255);
        if(key==-1) printf("ftok error:%m\n"),exit(-1);
        
        shmid=shmget(key,4,IPC_CREAT|IPC_EXCL|0666);
        if(shmid==-1) printf("get error:%m\n"),exit(-1);
        //2.挂载共享内存shmat
        p=shmat(shmid,0,0);
        if(p==(int*)-1) printf("at error:%m\n"),exit(-1);
        //3.访问共享内存
        while(1)
        {
            *p=i;
            sleep(1);
            i++;
        }
        
    }
    View Code
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <signal.h>
    #include <sys/shm.h>
    #include <sys/ipc.h>
    key_t key;
    int shmid;
    int *p;
    void deal(int s)
    {
        if(s==2)
        {
            //4.卸载共享内存shmdt
            shmdt(p);
            exit(0);
        }
    }
    main()
    {
        signal(SIGINT,deal);    
        //1.创建共享内存shmget
        key=ftok(".",255);
        if(key==-1) printf("ftok error:%m\n"),exit(-1);
        
        shmid=shmget(key,4,0);
        if(shmid==-1) printf("get error:%m\n"),exit(-1);
        //2.挂载共享内存shmat
        p=shmat(shmid,0,0);
        if(p==(int*)-1) printf("at error:%m\n"),exit(-1);
        //3.访问共享内存
        while(1)
        {        
            sleep(1);
            printf("%d\n",*p);
        }
    }

      3.内核共享队列(有序)
        编程模型:
          3.1.创建共享队列/得到队列msgget
          3.2.使用队列(发送消息msgsnd/接收消息msgrcv)
          3.3.删除队列msgctl
    案例:
       A:创建共享队列
         int msgget(key_t,int);      
       B:发送消息

        int msgsnd(
                int id,//消息队列ID
                const void *msg,//要发送消息
                size_t len,//消息的长度
                int flags//发送消息的方式,建议为0 
            );

         返回:
           -1:失败
            0:成功 
         第二个参数的消息有固定的格式
            4字节:表示消息的类型
            若干字节:消息内容。
         第三个参数:
            消息的大小,不包含类型的4个字节

    View Code
    #include <unistd.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    struct msgbuf
    {
        long type;
        char data[32];
    };
    main()
    {
        key_t key;
        int msgid;
        int i;
        struct msgbuf msg;
        
        //1创建消息队列
        key=ftok(".",200);
        if(key==-1) printf("ftok err:%m\n"),exit(-1);
        
        msgid=msgget(key,0/*IPC_CREAT|IPC_EXCL|0666*/);
        if(msgid==-1)printf("get err:%m\n"),exit(-1);
        //2构造消息
            
        //3发送消息
        for(i=1;i<=10;i++)
        {
            bzero(msg.data,sizeof(msg.data));
            msg.type=1;
            sprintf(msg.data,"MessageI:%d",i);
            msgsnd(msgid,&msg,sizeof(msg.data),0);
        }
        for(i=1;i<=10;i++)
        {
            bzero(msg.data,sizeof(msg.data));
            msg.type=2;
            sprintf(msg.data,"MessageII:%d",i);
            
            msgsnd(msgid,&msg,sizeof(msg.data),0);
        }
        //4删除队列
        //msgctl(msgid,IPC_RMID,0);
    }
    View Code
    #include <unistd.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    struct msgbuf
    {
        long type;
        char data[32];
    };
    main()
    {
        key_t key;
        int msgid;
        int i;
        struct msgbuf msg;
        //1得到消息队列
        key=ftok(".",200);
        if(key==-1) printf("ftok err:%m\n"),exit(-1);
        
        msgid=msgget(key,0);
        if(msgid==-1)printf("get err:%m\n"),exit(-1);
        //2构造消息
            
        //3接收消息
        while(1)
        {
            bzero(&msg,sizeof(msg));
            msg.type=2;
            msgrcv(msgid,&msg,sizeof(msg.data),2,0);
            printf("%s\n",msg.data);
        }
    }

    三.基于socket文件的IPC
     socket文件的通信方式,比较重要,原因:网络采用这种通信模型。
     两种模型:
        对等模型
        C/S模型
     1.对等模型:
        1.建立socket:socket

        int socket(
                    int domain,//地址族的类型AF_UNIX AF_INET
                    int type,//支持的数据格式:流SOCK_STREAM/报文SOCK_DGRAM
                    int protocol);//支持的协议,建议为0 

          返回值:
            成功返回文件描述符号。
            失败返回-1;
        2.绑定在地址上(文件目录地址)URL(Universe Resource Location)
          协议://路径/文件名
          file:///usr/bin/ls
          http://192.168.0.72/index.php
          struct sockaddr;
          struct sockaddr_un;un=unix
          struct sockaddr_in;in=internet

        int bind(int fd,//socket描述符号
                struct sockaddr*addr,//绑定地址
                socklen_t size);//地址长度

        3.接收数据
          read/recv/recvfrom
        4.关闭socket

    View Code
    #include <sys/socket.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <linux/un.h>
    
    main()
    {
        int fd;
        int r;
        char buf[200];
        //1.建立socket
        fd=socket(AF_UNIX,SOCK_DGRAM,0);
        if(fd==-1) printf("socket err:%m\n"),exit(-1);
        printf("socket成功!\n");
        //2.构造本地文件地址
        struct sockaddr_un addr={0};
        addr.sun_family=AF_UNIX;
        memcpy(addr.sun_path,"my.sock",
                        strlen("my.sock"));
        
        //3.把socket绑定在地址上
        r=bind(fd,(struct sockaddr*)&addr,sizeof(addr));
        if(r==-1) printf("bind err:%m\n"),exit(-1);
        printf("地址绑定成功!\n");
        
        //4.接收数据
        while(1)
        {
            bzero(buf,sizeof(buf));
            r=read(fd,buf,sizeof(buf));
            buf[r]=0;
            printf("%s\n",buf);
        }    
        
        //5.关闭
        close(fd);
        //6.删除socket文件
        unlink("my.sock");
        
    }

        1.建立socket:socket
        2.连接到目标:connect(可选)    
        3.发送数据:write/send/sendto
        4.关闭close

    View Code
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/socket.h>
    #include <linux/un.h>
    #include <string.h>
    #include <unistd.h>
    main()
    {
        int fd;
        int r;
        char buf[100];
        struct sockaddr_un addr={0};
        //1.建立socket
        fd=socket(AF_UNIX,SOCK_DGRAM,0);
        //2.连接到指定的地址
        addr.sun_family=AF_UNIX;
        memcpy(addr.sun_path,"my.sock",
                strlen("my.sock"));
        r=connect(fd,(struct sockaddr*)&addr,
                sizeof(addr));
        //3.发送数据
        while(1)
        {
            write(fd,"Hello!MaomaoYu!",
                strlen("Hello!MaomaoYu!"));
            sleep(1);    
        }
        //4.关闭
        close(fd);
    }
    View Code
    #include <sys/socket.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    //1.
    #include <netinet/in.h>
    #include <arpa/inet.h>
    
    main()
    {
        int fd;
        int r;
        char buf[200];
        //1.建立socket
        //2
        fd=socket(AF_INET,SOCK_DGRAM,0);
        if(fd==-1) printf("socket err:%m\n"),exit(-1);
        printf("socket成功!\n");
        //2.构造本地文件地址
        //3.
        struct sockaddr_in addr={0};
        addr.sin_family=AF_INET;
        addr.sin_port=htons(9999);
        addr.sin_addr.s_addr=
                inet_addr("192.168.180.92");
        //3.把socket绑定在地址上
        r=bind(fd,(struct sockaddr*)&addr,sizeof(addr));
        if(r==-1) printf("bind err:%m\n"),exit(-1);
        printf("地址绑定成功!\n");
        
        //4.接收数据
        while(1)
        {
            bzero(buf,sizeof(buf));
            r=read(fd,buf,sizeof(buf));
            buf[r]=0;
            printf("%s\n",buf);
        }    
        
        //5.关闭
        close(fd);
        //6.删除socket文件
        unlink("my.sock");
        
    }
    View Code
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/socket.h>
    #include <string.h>
    #include <unistd.h>
    //1
    #include <netinet/in.h>
    #include <arpa/inet.h>
    main()
    {
        int fd;
        int r;
        //2
        struct sockaddr_in addr={0};
        //1.建立socket
        //3
        fd=socket(AF_INET,SOCK_DGRAM,0);
        //2.连接到指定的地址
        //4
        addr.sin_family=AF_INET;
        addr.sin_port=htons(9999);
        addr.sin_addr.s_addr
            =inet_addr("192.168.180.92");
        
        r=connect(fd,(struct sockaddr*)&addr,
                sizeof(addr));
        //3.发送数据
        write(fd,"Hello!Maomaochong!",
            strlen("Hello!Maomaochong!"));
        //4.关闭
        close(fd);dd
    }

     2.C/S模型
       Server            Client
       建立socket:socket   建立socket:socket
       绑定地址:bind       建立连接:connect
       监听:listen   
       接收:accept    
       read/write         read/write
       close             close
       
       int listen(int fd,int num);
         0:监听成功
         -1:失败

    int accept(int fd,
            struct sockaddr*addr,//返回连接着的地址
            socklen_t* len)//接收返回地址的缓冲长度

       返回: 
         -1:接收失败
         >=0:对应客户的文件描述符号 

    View Code
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <linux/un.h>
    
    main()
    {
        int sfd;
        int cfd;
        struct sockaddr_un addr;
        int r;
        char buf[100];
        //1.建立socket
        sfd=socket(AF_UNIX,SOCK_STREAM,0);
        if(sfd==-1) printf("socket err:%m\n"),exit(-1);
        printf("建立socket成功!\n");
        
        //2.绑定地址
        bzero(&addr,sizeof(addr));
        addr.sun_family=AF_UNIX;
        memcpy(addr.sun_path,"cs.sock",
            strlen("cs.sock")+1);
        r=bind(sfd,(struct sockaddr*)&addr,sizeof(addr));
        if(r==-1) printf("bind err:%m\n"),exit(-1);
        printf("bind成功!\n");
        
        //3.监听
        r=listen(sfd,10);
        if(r==-1) printf("listen err:%m\n"),exit(-1);
        printf("listen成功!\n");
        
        //4.接收客户
        cfd=accept(sfd,0,0);
        if(cfd==-1) printf("accept err:%m\n"),exit(-1);
        printf("建立连接者的状态成功!\n");
        //5.接收这个客户的数据
        while(1)
        {
            r=read(cfd,buf,sizeof(buf));
            if(r==0)
            {
                printf("连接者退出");
                break;
            }
            if(r==-1)
            {
                printf("scoket故障!\n");
                break;
            }
            buf[r]=0;
            printf("::%s\n",buf);
            write(cfd,"Hi",2);
            
        }
        //6.关闭客户
        close(cfd);
        //7.关闭整个socket
        close(sfd);
        
    }
    View Code
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/socket.h>
    #include <linux/un.h>
    #include <string.h>
    #include <unistd.h>
    main()
    {
        int fd;
        int r;
        char buf[100];
        struct sockaddr_un addr={0};
        //1.建立socket
        //fd=socket(AF_UNIX,SOCK_DGRAM,0);
        fd=socket(AF_UNIX,SOCK_STREAM,0);
        //2.连接到指定的地址
        addr.sun_family=AF_UNIX;
        memcpy(addr.sun_path,"cs.sock",
                strlen("cs.sock"));
        r=connect(fd,(struct sockaddr*)&addr,
                sizeof(addr));
        //3.发送数据
        while(1)
        {
            write(fd,"Hello!MaomaoYu!",
                strlen("Hello!MaomaoYu!"));
            read(fd,buf,100);
            printf("%s\n",buf);
            sleep(1);    
        }
        //4.关闭
        close(fd);
    }

    总结:
       共享内存
       共享队列
       socket文件通信
    课堂练习:
       CS模型代码
       CS模型把socket文件替换成IP地址

    课后作业:
       模仿课堂案例独立完成      
         1.共享内存
         2.共享队列
         3.socket对等模型
         4.socket的CS模型

  • 相关阅读:
    python_接口基础知识
    python_基础总结
    python_配置文件_yaml
    python_loggin日志处理
    python_数据驱动_ddt
    python_unittest_单元测试_openpyxl
    python_类与对象总结_继承
    python_路径操作及类和对象
    python_导包
    Codeforces Round #655 (Div. 2) B. Omkar and Last Class of Math
  • 原文地址:https://www.cnblogs.com/tangzhengyue/p/2650784.html
Copyright © 2011-2022 走看看