一、使用信号量集实现进程间的通信
1.1 基本概念
(1)什么是信号量???
信号量本质上就是一个计数器,用于控制同时访问同一种共享资源的进程 / 线程个数;
-
如:
- 图书馆 Unix环境高级编程 5本 信号量 = 5
(2)信号量的工作方式
a. 首先初始化信号量为最大值;
b. 当有进程申请到共享资源时,信号量的数值减1;
c. 当信号量的数值为0时,申请共享资源的进程进入阻塞状态;
d. 当有进程释放共享资源时,信号量的数值加1;
e. 只要信号量的数值>0,则阻塞的进程可以继续抢占共享资源,抢占不到的进程继续阻塞;
(3)什么是信号量集???
信号量集本质上就是由若干个信号量组成的集合,用于控制多种共享资源分别被同时访问的进程 / 线程个数;
-
扩展:
- 信号量集:semaphore set
1.2 通信模型
(1)获取key值,使用ftok();
(2)创建 / 获取信号量集,使用semget();
(3)初始化 / 操作信号量集,使用semctl() / semop();
(4)如果不再使用,则删除信号量集,使用semctl();
1.3 相关函数的解析
(1)semget()
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg);
功能:
主要用于创建 / 获取信号量集;
参数:
第一个参数:key值,ftok()的返回值;
第二个参数:信号量集的大小,也就是信号量的个数;
0 - - - - - - - - - - - - – 获取已经存在的操作标志
第三个参数:具体的操作标志
IPC_CREAT - - - - - 若存在则打开,若不存在则创建
IPC_EXCL - - - - - - 与IPC_CREAT搭配使用,若存在则创建失败
0 - - - - - - - - - - - - - -获取已经存在的信号量集
返回值:
success —- 信号量集的ID,error —- -1;
注意:
当创建新的信号量集时,需要在第三个参数中通过按位或的方式指定权限信息,如:0664;
(2)semctl()
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semctl(int semid, int semnum, int cmd, ...);
功能:
主要用于控制参数指定的信号量集;
参数:
第一个参数:信号量集的ID,semget()的返回值;
第二个参数:信号量集的下标,从0开始;
第三个参数:具体的操作命令;
IPC_RMID - - - - - - 删除信号量集,忽略第二个参数,不需要第四个参数
SETVAL - - - - - - - -使用第四个实参给下标为semnum的信号量初始化
SETALL - - - - - - - -
第四个参数:可变长参数,是否需要取决于cmd;
(3)semop()
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semop(int semid, struct sembuf *sops, size_t nsops);
功能:
主要用于操作指定的信号量集;
参数:
第一个参数:信号量集的ID,semget()的返回值;
第二个参数:结构体指针,可以指向结构体变量,也可以指向结构体数组;
struct sembuf
{
unsigned short sem_num; /* 信号量集的下标 */
short sem_op; /* 信号量的操作:正数表示增加、负数表示减少、0表示不变 */
short sem_flg; /* 操作标志,默认给0 */
}
第三个参数:结构体变量的个数;
当第二个参数指向结构体变量时,该参数的数值为1
当第二个参数指向结构体数组时,该参数为数组元素的个数
1.4 常用的基本命令
$ ipcs -s
- - - - - - 表示查看系统中已经存在的信号量集
$ ipcrm -s
- - - - - 信号量集的ID表示删除指定的信号量集
$ ipcs -a
- - - - - - 表示查看系统中已经存在的所有IPC结构
二、网络的基本常识
如:
目前主流的网络通讯软件:QQ 微信 飞信 阿里旺旺 …
2.1 七层网络协议模型和常用的网络协议
(1)七层网络协议模型
为了数据完整、安全地在网络中传递,ISO将数据的传递从逻辑上划分为以下七层:
应用层 - - - - - - - - - 主要用于将数据提交给应用程序,如:QQ等;
表示层 - - - - - - - - - 主要用于按照统一的格式进行数据的封装等;
会话层 - - - - - - - - - 主要用于控制对话的建立、关闭等操作;
传输层 - - - - - - - - - 主要用于进行数据的检查和重新排序等;
网络层 - - - - - - - - - 主要用于选择具体网络协议再次封装和发送等;
数据链路层 - - - - – 主要用于将数据转换为高低电平信号等;
物理层 - - - - - - - - - 主要指交换机等网络设备;
扩展:
IOS,即国际标准化组织(International Organization for Standardization)
(2)常用的网络协议
a. TCP协议 (Transmission Control Protocol )
传输控制协议,是一种面向连接的协议,类似打电话;
b. UDP协议(User Datagram Protocol )
用户数据报协议,是一种非面向连接的协议,类似写信;
c. IP协议(Internet protocol )
互联网协议,是上述两种协议的底层协议;
2.2 IP地址和子网掩码(重点)
(1)IP地址
- IP地址 - 是互联网中的唯一地址标识,其本质上就是一个由32位二进制组成的整数(IPv4),也有128位二进制组成的整数(IPv6);
- 日常生活中采用点分十进制表示法来描述IP地址,也就是将每一个字节的二进制转换为一个十进制的整数,不同的整数之间采用小数点分隔;
为了便于IP地址的管理,将IP地址分为网络地址和主机地址两部分,根据IP地址中网络地址和主机地址的位数不同分为五类:
查看系统的IP地址的方式
windows系统:在dos窗口中使用命令ipconfig可以查看;
Linux系统:在终端中使用$ ifconfig
或者$ /sbin/ifconfig
(2)子网掩码
主要用于划分IP地址中的网络地址和主机地址,以及判断两个IP地址是否在同一个子网中,具体的划分方法为:IP地址 & 子网掩码 = 网络地址 + 主机地址;
如:
IP地址:172.30.3.105 => 网络地址:172.30.3.0
子网掩码:255.255.255.0 主机地址:0.0.0.105
练习:
判断以下两个IP地址是否在同一个局域网中???
166.111.161.1与166.111.160.45
子网掩码都是:255.255.254.0
2.3 端口号和字节序(重点)
(1)端口号
网络编程中需要提供:IP地址 + 端口号;
IP地址 - - - - - - - 定位到具体的某一台主机/设备;
端口号 - - - - - - - 定位到主机上的具体某个进程;
端口号本质上就是unsigned short类型,范围是0~65535,其中0~1024之间的端口号被系统占用,因此编程从1025开始使用;
(2)字节序
小端系统:主要指将低位数据存放在低位内存地址的系统;
大端系统:主要指将低位数据存放在高位内存地址的系统;
如:
对于数据0x12345678来说,不同的系统的存放形式如下:
小端系统按照地址从小到大:0x78 0x56 0x34 0x12
大端系统按照地址从小到大:0x12 0x34 0x56 0x78
一般性原则:
一般来说,对于所有发送到网络中的多字节整数来说,先转换为网络字节序再发送,而对于所有从网络中接收过来的多字节整数来说,需要先转换为主机字节序再解析,而网络字节序本质上就是大端系统的字节序;
三、基于socket的一对一通信模型
3.1 基本概念
socket本意为“插座”,这里指“逻辑通信载体”;
3.2 通信模型
主机A:
(1)创建socket,使用socket();
(2)准备通信地址,使用结构体类型;
(3)绑定socket和通信地址,使用bind();
(4)进行通信,使用read() / write();
(5)关闭socket,使用close();
主机B:
(1)创建socket,使用socket();
(2)准备通信地址,使用主机A的地址;
(3)连接socket和通信地址,使用connect();
(4)进行通信,使用read() / write();
(5)关闭socket,使用close();
练习:
查询通信模型中的相关函数;
明日预报:
(1)网络编程