我要成为嵌入式高手之3月5日Linux高编第十五天!!
______________________________________________________
学习笔记
有名信号量
1、创建semget
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg);
功能:创建一组信号量
参数:
key:IPC对象的key值
nsems:信号量的个数
semflag: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, ...);
功能:向信号灯发送命令
参数:
semdi:信号灯ID号
semnum:具体操作信号量的编号
cmd:命令
IPC_SET:设置权限
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
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semop(int semid, struct sembuf *sops, size_t nsops);
unsigned short sem_num; /* semaphore number */(操作的信号量的下标)
short sem_op; /* semaphore operation */(具体对信号量的操作,申请-1,释放+1)
short sem_flg; /* operation flags */(信号量完成某个操作)
参数:
semid:信号灯的id号
sops:信号量操作的数组的首地址
nsops:数组元素个数
返回值:成功0,失败-1;
4、释放semop
和申请是同一个函数
网络
用处:数据共享、数据传输
一、网络协议模型
OSI协议模型
是一种分层模型,下一层为上一层提供服务
应用层:实际发送的数据
表示层:发送的数据是否要加密
会话层:是否建立会话链接
传输层:数据传输的方式(数据报、流式传输)
网络层:数据的路由(如何从一个局域网到达另一个局域网)IP地址
数据链路层:局域网下如何通信
物理层:物理介质的连接
TCP / IP协议模型
应用层:传输的数据
传输层:传输的方式
网络层:数据如何从一台主机到达另一台主机
网络接口层:物理介质的连接
应用层
HTTP协议:超文本传输协议
HTTPS协议:加密的HTTP协议
FTP协议:文件传输协议
TFTP协议:简单文本传输协议
SMTP协议:邮件传输协议
MQTT协议
TELNET协议
传输层
UDP协议
用户数据报协议
特点:
1、实现机制简单
2、资源开销小
3、不安全不可靠
TCP协议
传输控制协议
特点:
1、实现机制复杂
三次握手建立连接
2、资源开销大
3、安全可靠
四次挥手断开链接
网络层
IPV4
IP地址:唯一标识网络当中的 一台主机的标号
IP地址:网络位+主机位
子网掩码:用来标识IP地址的网络位和主机位
子网掩码是1的部分表示IP地址的网络位
子网掩码是0的部分表示IP地址的主机位
网段号:主网络位不变,机位全为0,表示网段号(192.168.1.0)
广播地址:网络位不变,主机位全为1,表示广播地址(192.168.1.255)
IP地址类型:
A类:1.0.0.0 — 126.255.255.255
子网掩码:255.0.0.0(可以容纳1677724台主机)
管理超大规模网络
10.0.0.0 — 10.255.255.255(私有地址)
B类:128.0.0.0 — 191.255.255.255
子网掩码:255.255.0.0(可以容纳65534台主机)
管理大中规模型网络
C类:192.0.0.0 — 223.255.255.255
子网掩码:255.255.255.0(可以容纳254台主机)
管理中小型规模网络
D类:224.0.0.0 — 239.0.0.0
用于组播
E类:240.0.0.0 — 255.255.255.255
用于实验
MAC地址
网卡物理地址,是唯一的
二、UDP编程
socket套接字编程:
1、发送端
①socket
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
功能:创建一个用来通信的文件描述符
参数:
domain:通信使用的协议族 AF_INET(IPv4协议族)
type:套接字类型
SOCK_STREAM 流式套接字
SOCK_DGRAM 数据报套接字
SOCK_RAW:原始套接字
protocol:协议,默认传0
返回值:成功返回文件描述符,失败返回-1;
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
②sendto
#include <sys/types.h>
#include <sys/socket.h>
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
功能:利用套接字向指定地址发送数据信息
参数:
sockfd:套接字文件描述符
buf:发送数据空间首地址
len:发送数据的长度
flages:发送的属性默认为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 */(端口号,不要用10000以下)
struct in_addr sin_addr; /* internet address */(IP地址)
};
/* Internet address. */——结构体中的sin_addr
struct in_addr {
uint32_t s_addr; /* address in network byte order */
};
结合起来为:recvaddr.sin_addr.s_addr(转换为32位的ip地址)
返回值:成功返回实际发送的字节数,失败返回-1;
③inet_addr:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
in_addr_t inet_addr(const char *cp);
功能:将字符串IP地址转换为内存当中的IP地址
④htons
uint16_t htons(uint16_t hostshort);
功能:将本地字节序转换成网络的大端字节序
#include "head.h"
int main(void)
{
int sockfd = 0;
struct sockaddr_in recvaddr;
char tmpbuff[1024] = {"how are you?"};
ssize_t nsize = 0;
/*创建用来通信的UDP套接字*/
sockfd = socket(AF_INET, SOCK_DGRAM, 0);//通信使用的协议族(AF_INET是IPv4协议族),套接字类型:数据报套接字;默认0
if (-1 == sockfd)
{
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.1.101");//函数接口inet_addr将字符串的ip地址转换为内存当中的IP地址
//前面是ip地址转换为32位之后的变量名
/*发送信息*/
nsize = sendto(sockfd, tmpbuff, strlen(tmpbuff), 0, (struct sockaddr *)&recvaddr, sizeof(recvaddr));
//0为发送的属性,默认为0,发送到哪里(那个空间的首地址),那个地方的空间大小
if (-1 == nsize)
{
perror("fail to sendto");
return -1;
}
printf("成功发送%ld字节!\n", nsize);
close(sockfd);
return 0;
}
2、接收端
recvfrom