博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
linux高级编程day08 笔记
阅读量:6004 次
发布时间:2019-06-20

本文共 9485 字,大约阅读时间需要 31 分钟。

一.基于文件的通信

  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 
#include
#include
#include
#include
#include
#include
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 
#include
#include
#include
#include
#include
#include
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 
#include
#include
#include
#include
#include
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 
#include
#include
#include
#include
#include
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
      
      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 
#include
#include
#include
#include
#include
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 
#include
#include
#include
#include
#include
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 
#include
#include
#include
#include
//1.#include
#include
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 
#include
#include
#include
#include
//1#include
#include
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 
#include
#include
#include
#include
#include
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 
#include
#include
#include
#include
#include
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模型

转载于:https://www.cnblogs.com/tangzhengyue/archive/2012/08/22/2650784.html

你可能感兴趣的文章
JavaScript之手写Promise
查看>>
PHP_SELF变量解析和重复路径解决
查看>>
git 命令行使用(基础篇)
查看>>
Vue笔记(五)——Token&生命周期
查看>>
《前端十年心路-我把一切告诉你》的书稿大纲&问题收集
查看>>
CSS居中总结大全
查看>>
Elasticsearch 参考指南(安装X-Pack)
查看>>
[LintCode] 604. Design Compressed String Iterator
查看>>
微信小程序黑客马拉松即将开始,来做最酷的 Mini Program Creators!
查看>>
JavaScript基础---函数
查看>>
前端每日实战:120# 视频演示如何用纯 CSS 创作锡纸撕开的文字效果
查看>>
Laravel实用小功能
查看>>
matplotlib绑定到PyQt5(有菜单)
查看>>
利用Powershell和ceye.io实现Windows账户密码回传
查看>>
Windows 8.1 今年 1 月市场份额超 Vista
查看>>
《设计团队协作权威指南》—第1章1.5节总结
查看>>
【PMP认证考试之个人总结】第 5 章 项目时间管理
查看>>
Chair:支付宝前端团队推出的Node.js Web框架
查看>>
《Total Commander:万能文件管理器》——第3.8节.后续更新
查看>>
BSD vi/vim 命令大全(下)[转]
查看>>