苏嵌实训——day17(上)

简介: 苏嵌实训——day17(上)

一 IPC通信之 信号灯集

信号灯集:是在内核空间的信号灯的集合

0a2653c851af460fa595bd959398a8f1.png


1.1 信号灯集函数接口


1.semget


头文件:#include <sys/types.h>
       #include <sys/ipc.h>
       #include <sys/sem.h>
原型:int semget(key_t key, int nsems, int semflg);
功能:创建或者打开一个信号灯集
参数:
    key:信号灯集的秘钥(和共享内存,消息队列类似)
    nsems:创建的信号灯集中存在几个信号灯
    semflg:打开的方式
        IPC_CREAT:如果共享内存存在,则打开,不存在则创建
        例如:IPC_CREAT | 0664
        IPC_EXCL:如果存在则报错返回,如果不存在配合IPC_CREAT创建
返回值:
    成功返回一个信号灯集的ID
    失败返回-1


2.semctl


头文件:#include <sys/types.h>
       #include <sys/ipc.h>
       #include <sys/sem.h>
原型:int semctl(int semid, int semnum, int cmd, ...);
功能:控制信号灯集
参数:
    semid:要控制的信号灯集的ID号
    semnum:信号灯的编号
    cmd:控制方式
        IPC_RMID:删除信号灯集,不考虑第二个参数
        GETVAL:获取信号灯的值
        SETVAL:设置信号灯的值
    ..:可变参数:是一个联合体
        union semun {
               int              val;    /* Value for SETVAL */
               struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
               unsigned short  *array;  /* Array for GETALL, SETALL */
               struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                           (Linux-specific) */
           };          
返回值:
    成功返回 0
    GETVAL:返回一个信号灯的值
    失败返回-1


3.封装初始化函数


int sem_init_val(int semid,int semnum,int val)
{
    union semun myval;  //需要自己定义
    myval.val = val;
    if(-1 ==semctl(semid,semnum,SETVAL,myval))
    {
        printf("初始化信号灯%d失败\n",semnum);
        return -1;   
    }
    return 0;
}


4. semop


头文件:#include <sys/types.h>
       #include <sys/ipc.h>
       #include <sys/sem.h>
原型:int semop(int semid, struct sembuf *sops, size_t nsops);
功能:操作方式
参数:
semid:信号灯集的ID号
sops:操作方法结构体的地址
    unsigned short sem_num;  /* semaphore number */
    short          sem_op;   /* semaphore operation */
    short          sem_flg;  /* operation flags */
    使用案例:
         struct sembuf sops[2];
           int semid;
           /* Code to set semid omitted */
           sops[0].sem_num = 0;        /* Operate on semaphore 0 */
           sops[0].sem_op = 0;         /* Wait for value to equal 0 */
           sops[0].sem_flg = 0;
           sops[1].sem_num = 0;        /* Operate on semaphore 0 */
           sops[1].sem_op = 1;         /* Increment value by one */
           sops[1].sem_flg = 0;
           if (semop(semid, sops, 2) == -1) {
               perror("semop");
               exit(EXIT_FAILURE);
           }
nsops:同时操作的个数
    如果说同时操作很多信号灯,填写一个结构体数组                                    
返回值:
    成功返回0
    失败返回-1


//write
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
union semun {
    int  val;    /* Value for SETVAL */
};
int sem_init_val(int semid,int semnum,int val)
{
    union semun myval;  //需要自己定义
    myval.val = val;
    if(-1 ==semctl(semid,semnum,SETVAL,myval))
    {
        printf("初始化信号灯%d失败\n",semnum);
        return -1;   
    }
    return 0;
}
int sem_p(int semid,int semnum) //参数1:信号灯集  2.信号灯的编号
{   
    struct sembuf mybuf;
    mybuf.sem_num = semnum;        /* Operate on semaphore 0 */
    mybuf.sem_op = -1;         /* Wait for value to equal 0 */
    mybuf.sem_flg = 0;
    if(-1 == semop(semid,&mybuf,1))
    {
        printf("p操作失败\n");
        return -1;
    }
    return 0;
}
int sem_v(int semid,int semnum) //参数1:信号灯集  2.信号灯的编号
{   
    struct sembuf mybuf;
    mybuf.sem_num = semnum;        /* Operate on semaphore 0 */
    mybuf.sem_op = 1;         /* Wait for value to equal 0 */
    mybuf.sem_flg = 0;
    if(-1 == semop(semid,&mybuf,1))
    {
        printf("v操作失败\n");
        return -1;
    }
    return 0;
}
int main(int argc, char const *argv[])
{
    //生成一个共享内存使用的key值
    key_t mykey1 = ftok("/home/jsetc/jsetc/208/",'a');
    if(-1 == mykey1)
    {
        perror("生成键值失败");
        return -1;
    }
    //生成一个自定义key值
    key_t mykey = ftok("/home/jsetc/jsetc/208/day17/",'a');
    if(-1 == mykey)
    {
        perror("ftok");
        return -1;
    }
    //创建信号灯集
    int semid = semget(mykey,2,IPC_CREAT | 0664);
    if(-1 == semid)
    {
        perror("semget");
        return -1;
    }
    //初始化信号灯集
    sem_init_val(semid,0,1);
    sem_init_val(semid,1,0);
    //创建共享内存
    int shmid = shmget(mykey1,4096,IPC_CREAT | 0664);
    if(-1 == shmid)
    {
        perror("shmget");
        return -1;
    }
    printf("创建或者打开共享内存成功\n");
    //地址映射
    char *buf = (char *)shmat(shmid,NULL,0);
    if((char *)-1 == buf)
    {
        perror("shmat");
        return -1;
    }
    while(1)
    {
        sem_p(semid,0);    //p操作
        printf("请输入\n");
        scanf("%s",buf);
        sem_v(semid,1);
    }
    return 0;
}


#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
union semun {
    int  val;    /* Value for SETVAL */
};
int sem_init_val(int semid,int semnum,int val)
{
    union semun myval;  //需要自己定义
    myval.val = val;
    if(-1 ==semctl(semid,semnum,SETVAL,myval))
    {
        printf("初始化信号灯%d失败\n",semnum);
        return -1;   
    }
    return 0;
}
int sem_p(int semid,int semnum) //参数1:信号灯集  2.信号灯的编号
{   
    struct sembuf mybuf;
    mybuf.sem_num = semnum;        /* Operate on semaphore 0 */
    mybuf.sem_op = -1;         /* Wait for value to equal 0 */
    mybuf.sem_flg = 0;
    if(-1 == semop(semid,&mybuf,1))
    {
        printf("p操作失败\n");
        return -1;
    }
    return 0;
}
int sem_v(int semid,int semnum) //参数1:信号灯集  2.信号灯的编号
{   
    struct sembuf mybuf;
    mybuf.sem_num = semnum;        /* Operate on semaphore 0 */
    mybuf.sem_op = 1;         /* Wait for value to equal 0 */
    mybuf.sem_flg = 0;
    if(-1 == semop(semid,&mybuf,1))
    {
        printf("v操作失败\n");
        return -1;
    }
    return 0;
}
int main(int argc, char const *argv[])
{
    //生成一个共享内存使用的key值
    key_t mykey1 = ftok("/home/jsetc/jsetc/208/",'a');
    if(-1 == mykey1)
    {
        perror("生成键值失败");
        return -1;
    }
    //生成一个自定义key值
    key_t mykey = ftok("/home/jsetc/jsetc/208/day17/",'a');
    if(-1 == mykey)
    {
        perror("ftok");
        return -1;
    }
    //创建信号灯集
    int semid = semget(mykey,2,IPC_CREAT | 0664);
    if(-1 == semid)
    {
        perror("semget");
        return -1;
    }
    //初始化信号灯集
    sem_init_val(semid,0,1);
    sem_init_val(semid,1,0);
    //创建共享内存
    int shmid = shmget(mykey1,4096,IPC_CREAT | 0664);
    if(-1 == shmid)
    {
        perror("shmget");
        return -1;
    }
    printf("创建或者打开共享内存成功\n");
    //地址映射
    char *buf = (char *)shmat(shmid,NULL,0);
    if((char *)-1 == buf)
    {
        perror("shmat");
        return -1;
    }
    while(1)
    {
        sem_p(semid,1);    //p操作
        printf("buf = %s\n",buf);
        sem_v(semid,0);
    }    
    return 0;
}


二 网络编程


2.1 为什么要学习网络编程


网络编程就是最后一种进程间通信的方式-----》套接字通信

套接字通信:前六种进程间通信只能实现同一台主机的多个进程通信,但是套接字通信可以实现不同主机的多个进程间通信。


2.2 发展


Arpanet

TCP/IP协议:一共两个协议

网络体系结构:发明了osi开放系统互联模型

TCP/IP协议族:有很多个协议组成


2.2.1 ARPnet


是网络的最早雏形

不能互联不同类型的计算机和不同类型的操作系统,没有纠错功能。


2.2.2 TCP/IP协议


TCP/IP协议分成了两个不同的协议:

用来检测网络传输中差错的传输协议:TCP

专门分则对不同网络进行互联的互联网协议:IP


2.3 网络体系结构以及OSI开放系统互联模型


OSI(国际标准化组织)提供的一个网络体系结构

OSI因为层次结构比较复杂,所以到目前也没有使用,但是他是最早提出的网络体系结构

OSI七层模型:

应用层: 面向用户的,应用程序

表示层:对数据进行加密和解密

会话层:建立逻辑名字和物理名字之间的关系

运输层:用于控制数据的有效传输

网络层:数据分组,路由选择

数据链路层:将数据组成发送或者接收的帧数据

物理层:选择物理介质

注意:每个层次之间的顺序是不能改变的


2.4 TCP/IP协议族


后期基于OSI发明了TCP/IP协议族,这个协议族由很多协议组成:

TCP/IP协议族一共四层:

应用层:telnet,www,FTP,TFTP,SIP

传输层:tcp udp

网络层:IP,ICMP

网络接口与物理层:网卡驱动,物理接口


2.5 五层模型


应用层:

传输层:

网络层:

数据链路层:

物理层:


2.6 TCP和UDP的异同点


相同点:
    同为传输协议
不同点:
    TCP是面向连接的,可靠的,基于字节流的传输协议
    UDP是面向无连接,不可靠的,基于数据报的传输协议
Tcp的概念
    是一种面向链接的传输协议,它能提供高可靠性的通信(即数据无误,数据不丢失,数据无失序,数据无重复的到达),TCP有回传机制
    使用情况:
        适合对于传输质量要求较高,以及传输大量数据的通信,比图MSN/QQ登录,账号管理时需要使用TCP协议
UDP的概念
    是不可靠的,无连接的传输协议,在数据发送前,因为不需要进行链接,所以可以高效率的数据传输
    使用情况:
        适用于对于实时性要求较高的场景,比如:流媒体


2.7 函数讲解


2.7.1 socket


头文件:#include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>
原型:int socket(int domain, int type, int protocol);
功能:创建套接字,返回一个文件描述符
参数:
    domain:通信域
       AF_UNIX, AF_LOCAL   Local communication              unix(7)   //本地通信
       AF_INET             IPv4 Internet protocols          ip(7)    //ipv4网络协议
       AF_INET6            IPv6 Internet protocols          ipv6(7)   //ipv6网络协议
       AF_IPX              IPX - Novell protocols
       AF_NETLINK          Kernel user interface device     netlink(7)
       AF_X25              ITU-T X.25 / ISO-8208 protocol   x25(7)
       AF_AX25             Amateur radio AX.25 protocol
       AF_ATMPVC           Access to raw ATM PVCs
       AF_APPLETALK        AppleTalk                        ddp(7)
       AF_PACKET           Low level packet interface       packet(7)   //底层协议通信
       AF_ALG              Interface to kernel crypto API
    type:套接字类型
       SOCK_STREAM   :流式套接字   --->tcp  
       SOCK_DGRAM   : 数据报套接字 --->udp
       SOCK_RAW :      原始套接字
    protocol:附加协议,传0表示不需要其他协议
返回值:
    成功:文件描述符
    失败: -1


2.7.2 bind()


头文件:#include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>
原型:int bind(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
功能:将套接字与网络信息结构体绑定
参数:
    sockfd:文件描述符,socket的返回值
    addr:网络信息结构体
    通用结构体:一般不用
        struct sockaddr {
               sa_family_t sa_family;
               char        sa_data[14];
           }
    网络信息结构体:                                 
        stuct sockaddr_in{
            sa_family_t sin_family;   //地址族:AF_INET
            in_port_t  sin_port;    //网络字节序的端口号
            struct in_addr sin_addr  //ip地址   
                ---》struct in_addr
                    {
                        uint32_t s_addr;    //网络字节序的无符号4字节整数Ip地址                    
                    }                                  
        }
        addrlen:addr的大小
返回值:
    成功:返回0
    失败:返回-1


相关文章
|
6月前
|
Java 关系型数据库 MySQL
|
消息中间件 Linux
苏嵌实训——day16(下)
苏嵌实训——day16(下)
苏嵌实训——day16(下)
|
Ubuntu API 数据库
苏嵌实训——day19
苏嵌实训——day19
110 0
苏嵌实训——day19
|
网络协议 安全 网络安全
苏嵌实训——day18
苏嵌实训——day18
109 0
苏嵌实训——day18
|
存储 程序员 Linux
苏嵌实训——day14(上)
苏嵌实训——day14(上)
苏嵌实训——day14(上)
|
存储
苏嵌实训——day9(上)
苏嵌实训——day9(上)
苏嵌实训——day9(上)