1.有名信号量
操作共享内存的步骤: ftok生成一个key值 ->通过key 用 smget 创建一组信号量(下标0,1区分),返回一个信号灯的ID -> 对信号灯的初始化 (struct sembuf 结构体成员的赋值 ,成员sem_op中-1 是申请信号量,+1是释放信号量)-> 用semop去申请或者释放信号量)->
semctl 删除共享空间
1.创建:
semget
int semget(key_t key, int nsems, int semflg);
功能:创建一组信号量
参数:key:IPC对像的名字
nsems:信号量的数量
semflg:IPC_CREAT
返回值:成功返回信号量ID
失败返回-1
2.销毁
semctl
int semctl(int semid, int semnum, int cmd, ...);
功能:向信号灯发送命令
参数:semid:信号等的ID
semnum:具体操作信灯的编号
cmd: IPC_RMID 删除信号灯
SETVAL 设置信号量的值
返回值:成功返回0;失败返回-1;
初始化:
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) */
};
3.申请信号量 / 释放信号量
semop
int semop(int semid, struct sembuf *sops, size_t nsops);
功能:对信号量完成操作
参数:semid:信号灯的ID
sops:信号量操作的数组的首地址
nsops:数组元素的个数
返回值:成功返回0;失败返回-1;
unsigned short sem_num; /* semaphore number */ 操作信号量的下标
short sem_op; /* semaphore operation */ 具体对信号量的操作(申请:-1 释放:+1)
short sem_flg; /* operation flags */ SEM_UNDO
2. 网络(数据传输,数据共享):
1.网络协议模型
OSI协议模型:
应用层:实际发送的数据
表示层:发送的数据是否加密
会话层:是否建立会话连接
传输层:数据的传输方式(数据报,流式)
网络层:数据的路由(如何从一个局域网到达另外一个局域网) IP地址
数据链路层:局域网下如何通信
物理层:物理介质的连接
TCP/IP协议模型
应用层:传输的数据
传输层:传输的方式
网络层:数据如何从一台主机到达另一台主机
网络接口层:物质介质的连接
应用层: HTTP 超文本传输协议
hTTPS
FTP 文件传输协议
TFTP 简单文本传输协议
SMTP 邮件传输协议
MQTT
TELNET
传输层:
UDP 用户数据报协议
特点:
1.实现机制简单
2.资源开销小
3.不安全不可靠
TCP 传输控制协议
特点:
1.实现机制复杂(三次握手)
2.资源开销大
3.安全可靠(四次挥手)
网络层:
IPv4
IP地址:唯一标识网络中一台主机的标号
IP地址:网络位 + 主机位
子网掩码:用来标识IP地址的网络位和主机位
子网掩码是1的部分表示IP地址的网络位
子网掩码是0的部分表示IP地址的主机位
网段号:网络位不变,主机位全为0,表示网段号
广播地址:网络位不变,主机位全为1,表示广播地址
IP地址类型:
A类
1.0.0.0 - 126.255.255.255
子网掩码:255.0.0.0
管理超大规模网络
10.0.0.0 - 10.255.255.255
B类
128.0.0.0 - 191.255.255.255
子网掩码:255.255.0.0
管理大中规模型网络
172.16.0.0 - 172.31.255.255
C类
192.0.0.0 - 223.255.255.255
子网掩码:255.255.255.0
管理中小规模型网络
192.168.0.0 - 192.168.255.255
D类
224.0.0.0 - 239.0.0.0
用于组播
E类
240.0.0.0 - 255.255.255.255
用于实验
2.UDP编程
socket套接字编程 : socket 创建通信的文件描述符 -> struct sockaddr_in 结构体成员的赋值( inet_addr 将字符串地址转换为内存地址 ,htons 将本地字节序转换为网络的大端字节序) ->
sendto 向目标地址发送数据信息
1.发端:
socket
int socket(int domain, int type, int protocol);
功能:
创建一个用来通信的文件描述符
参数:
domain:使用的协议族 AF_INET (IPv4协议族)
type:套接字类型
SOCK_STREAM:流式套接字
SOCK_DGRAM:数据报套接字
SOCK_RAW:原始套接字
protocol:协议
默认为0
返回值:
成功返回文件描述符
失败返回-1
sendto
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
功能:
利用套接字向指定地址发送数据信息
参数:
sockfd:套接字文件描述符
buf:发送数据空间首地址
len:发送数据的长度
flags:属性默认为0
dest_addr:目的地址信息存放的空间首地址
addrlen:目的地址的长度
struct sockaddr_in {
sa_family_t sin_family; /* address family: AF_INET */
in_port_t sin_port; /* port in network byte order */
struct in_addr sin_addr; /* internet address */
};
/* Internet address. */
struct in_addr {
uint32_t s_addr; /* address in network byte order */
};
返回值:
成功返回实际发送字节数
失败返回-1
inet_addr:
in_addr_t inet_addr(const char *cp);
功能:
将字符串IP地址转换为内存中的IP地址
htons
uint16_t htons(uint16_t hostshort);
功能:
将本地字节序转换为网络的大端字节序
eg:
int main(void)
{int sockfd = 0;struct sockaddr_in recvaddr; //定义目的地址信息存放的结构体变量char tmpbuff[1024] = {0};char tm[1024] = {0};ssize_t nsize = 0;ssize_t msize = 0;int len = 0;fgets(tmpbuff,sizeof(tmpbuff),stdin);/*创建用来通信的UDP套接字 */sockfd = socket(AF_INET, SOCK_DGRAM, 0); //创建一个用来通信的文件描述符if(sockfd == -1){perror("fail to socket");return -1;}/* 对接收方地址赋值 */recvaddr.sin_family = AF_INET;recvaddr.sin_port = htons(50000); //将本地字节序转换为网络的大端字节序recvaddr.sin_addr.s_addr = inet_addr("192.168.136.1"); //将字符串IP地址转换内存中的ip地址len = sizeof(recvaddr);/*发送信息*/nsize = sendto(sockfd, tmpbuff, strlen(tmpbuff), 0, (struct sockaddr *)&recvaddr, sizeof(recvaddr)); //利用套接字向指定地址发送数据信息//套接字文件描述符,发送数据空间地址,地址大小,属性默认0,目的地地址信息存放的空间地址(强制转换),地址大小if (-1 == nsize){perror("fail to sendto");return -1;}printf("已发送%ld个字节!!!\n",nsize);memset(tmpbuff,0,sizeof(tmpbuff));msize= recvfrom(sockfd,tm,sizeof(tm),0,(struct sockaddr *)&recvaddr,&len);puts(tm);close(sockfd);return 0;
}