嵌入式学习---DAY29:网络

一、IPC进程间通信方式

1.共享内存---最高效的进程间通信方式

共享内存:是一块,内核预留的空间 ,最高效的通信方式 ,避免了用户空间 到 内核空间的数据拷

贝。

step1 产生key值 

 key_t ftok(const char *pathname, int proj_id);

功能:将pathname 和 proj_id 转换为 key值 

参数:pathname  //给一个路径名 ,proj_id   //工程id       eg: 'A'

返回值:成功 key值,失败 -1     


	key_t key = ftok("/",'A');

	if (key < 0)
	{
		perror("ftok fail");
		return -1;
	}

	printf("key = %d\n",key);

step2 通过key获取ipc对象 (共享内存)

申请对象:shmget()

 int shmget(key_t key, size_t size, int shmflg);

功能:使用唯一键值key向内核提出共享内存使用申请

参数:key   唯一键值,size  要申请的共享内存大小

shmflg 申请的共享内存访问权限,八进制表示(IPC_CREAT|0666)
          如果是第一个申请,则用IPC_CREAT
          如果要检测是否存在,用IPC_EXCL

返回值:成功 返回共享内存id,一般用shmid表示,失败  -1;

int shmid = shmget(key,1024,IPC_CREAT|0666);

	if (shmid < 0)
	{
		perror("shmget fail");
		return -1;
	}

	printf("shmid = %d\n",shmid);

step3 共享内存 绑定 

shmat ,映射对象:shmat()

void *shmat(int shmid, const void *shmaddr, int shmflg);

功能:将指定shmid对应的共享内存映射到本地内存。

参数:shmid 要映射的本地内存

           shmaddr 本地可用的地址,如果不确定则用NULL,表示由系统自动分配。
          shmflg  :0 表示读写,SHM_RDONLY, 只读

返回值:成功 返回映射的地址,一般等于shmaddr,失败 (void*)-1

void *p = shmat(shmid,NULL,0);

	if (p == (void *)-1)
	{
		perror("shmat fail\n");
		return -1;
	}

	int *q = p;

	*q = 10;
	printf("p = %p\n",p);
	printf("*q = %d\n",*q);

step4 解除绑定(映射)

撤销映射:shmdt

int shmdt(const void *shmaddr);

功能:将本地内存与共享内存断开映射关系。

参数:shmaddr 要断开的映射地址。

返回值:成功  0,失败  -1;

step5销毁IPC对象 

删除对象:shmctl

 int shmctl(int shmid, int cmd, struct shmid_ds *buf); 

功能:修改共享内存属性,也可以删除指定的共享内存对象。

参数:shmid 要删除的共享内存对象

            cmd    IPC_RMID 删除对象的宏

                       buff  NULL 表示只删除对象。

返回值:成功 0,失败 -1

IPC对象 -- 共享内存 、消息队列 、信号量集 

二、网络

网络:不同主机间的通信问题 

实现网络通信:物理层面 有一个 信息通路  (1.有线 2.无线 :5G、4G 3.星链 )

软件层面(逻辑层面) 也需要 一个通路 

网络编程     Open System Interconnect  (OSI网络模型) ios

注:  Open System Interconnection Reference Model,OSI/RM

          International Organization for Standardization  (IOS)

底层为上层提供服务。

每个层次中,都有自己的一套规范 --- 协议 


1.IP

用来标识网络中的一台主句 ---- 通过ip可以找到对应一台主机

本质: 32位整型数值              表示方式 点分十进制 

  ip地址的组成:网络号 + 主机号 

网络号 ---表示所处的网络 ,      主机号 ---表示能容纳的主机

端口号 ----用来表示主机中某一个具体(进行网络通信)进程 

ip+端口----进程在网络的 地址 

2. 网络编程(tcp / udp)

TCP(即传输控制协议):是一种面向连接的传输层协议,它能提供高可靠性通信(即数
据无误、数据无丢失、数据无失序、数据无重复到达的通信)

适用情况:1. 适合于对传输质量要求较高,以及传输大量数据的通信。

                2. 在需要可靠数据传输的场合,通常使用TCP协议

               3. QQ等即时通讯软件的用户登录账户管理相关的功能通常采用TCP协议

tcp协议特点:1. 面向连接   //类似打电话通话之前 ,必须先打通 

                    2. 可靠传输   //保证数据准确可靠 (tcp协议机制 里面的功能 )

                    3. 面向字节流程

UDP(User Datagram Protocol)用户数据报协议,是不可靠的无连接的协议。在数据发送前,因为不需要进行连接,所以可以进行高效率的数据传输。

适用情况:1. 发送小尺寸数据(如对DNS服务器进行IP地址查询时)
                  2. 在接收到数据,给出应答较困难的网络中使用UDP。(如:无线网络)
                  3. 适合于广播/组播式通信中。
                  4. MSN/QQ/Skype等即时通讯软件的点对点文本通讯以及音视频通讯通常采用UDP协议
                  5. 流媒体、VOD、VoIP、IPTV等网络多媒体服务中通常采用UDP方式进行实时数据传输

UDP特点:   1.不可靠 
                   2.无连接 
                   3.数据报  

编程

     编程模型 
     c/s    client server    客户端,服务器模型     --- 专用客户端 
     b/s    browser server   浏览器,服务器模型     --- 通用的客户端 
     p2p    peer to peer     点对点传输 

基于UDP c/s通信模型

client ---客户端 --- 角色  --- 主动的角色  

1.socket、2.sendto发数据 

server --- 服务器端 --角色 --- 被动的角色  

1.socket 、2.recvfrom接收数据 

socket:

1.一种特殊的文件 --- 专门用于网络通信(不同主机间的进程)

2.socket 编程接口  --- socket 函数 提供了一个可以访问 操作系统 网络功能的接口 

 int socket(int domain, int type, int protocol)

功能:程序向内核提出创建一个基于内存的套接字描述符    

参数:   domain --域 (范围) ---socket 用于什么范围的通信 (ipv4  ipv6 )
              domain  地址族,PF_INET == AF_INET ==>互联网程序
                                          PF_UNIX == AF_UNIX ==>单机程序

type    套接字类型:SOCK_STREAM  流式套接字 ===》TCP   

                                SOCK_DGRAM   用户数据报套接字===>UDP

                                 SOCK_RAW     原始套接字  ===》IP

protocol 协议 ==》0 表示自动适应应用层协议。

返回值:成功 返回申请的套接字文件描述符 ,失败  -1

#include <stdio.h>
#include <sys/types.h>	       /* See NOTES */
#include <sys/socket.h>

int main(int argc, const char *argv[])
{

	int fd = socket(AF_INET,SOCK_DGRAM,0);

	if (fd < 0)
	{
		perror("socket fail");
		return -1;
	}
	
	printf("fd = %d\n",fd);
	return 0;
}

sendto 发数据 

ssize_t sendto(                int sockfd,  //用于通信的socket对应的fd
                                const void *buf,  //表示要发送的数据所在的一块空间 
                                        size_t len,  //表示发送的字节数 
                                          int flags,  //0  --- 默认  
 const struct sockaddr *dest_addr,  //表示 要发送到的 地址 (网络地址 ip+端口号 ) 
                socklen_t addrlen   //表示dest_addr 这个参数的长度 
                );

返回值:成功  发送出去的字节的数 ,失败  -1 

端口号

(1) 作用

 唯一的标识一个进程

每一个应用程序进程有一个端口号,

通讯时区分数据包属于哪个应用程序进程

(2) 分类

端口号一般由IANA (Internet Assigned NumbersAuthority) 管理

众所周知端口:1~1023(1~255之间为众所周知端口,256~1023端口通常由UNIX系统占用)

                        知名端口号(已经分配给标准应用服务软件) 

如: http协议用到的端口号 80 

已登记端口:  1024~49151

                        注册端口号(非标准应用服务软件的软件可以申请的端口号范围)

                         动态或私有端口://50000 以上的端口号 
                  49152~65535 动态分配的端口号(系统动态分配给应用程序使用的)

(3) 长度:2字节(16bit) 

数字转换函数:1236234687

主机转网络:uint32_t htonl(uint32_t hostlong);
                      ipv4 192.168.0.1 1~65535
                      uint16_t htons(uint16_t hostshort);

网络转主机:host to net 
                      net to host 
                      uint32_t ntohl(uint32_t netlong);
                      uint16_t ntohs(uint16_t netshort);

htonl --- h(host) to n(network) l (long)  //32位的数据

htons --- h(host) to n(network) s (short) //16位的数据 

ntohl 

ntohs --- n(network) to h(host)  s (short) 

字符串转换函数:

 主机转网络:in_addr_t inet_addr(const char *cp);
                      inet_addr("192.168.1.20");
                      cli.sin_addr

网络转主机:char *inet_ntoa(struct in_addr in); //a -- ascii 

      

#include <stdio.h>
#include <sys/types.h>	       /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>
#include <string.h>

int main(int argc, const char *argv[])
{

	int fd = socket(AF_INET,SOCK_DGRAM,0);

	if (fd < 0)
	{
		perror("socket fail");
		return -1;
	}
	
	printf("fd = %d\n",fd);

	char buf[1024] = "hello udp\n";
	struct sockaddr_in seraddr;
	seraddr.sin_family = AF_INET;
	seraddr.sin_port = htons(50000);
	seraddr.sin_addr.s_addr = inet_addr("192.168.1.149");

	sendto(fd,buf,strlen(buf)+1,0,(const struct sockaddr *)&seraddr,sizeof(seraddr));

	return 0;
}

  • 23
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值