嵌入式学习【第七周】

Linux网络编程

day1:

1 网络基础

1.1 网络体系结构

网络设备=网络终端设备+网络中继(传输)设备
网络体系结构:网络的分层模型和每层所使用的协议的集合
有两种:OSI 7层 应用层 表示层 会话层 传输层 网络层 数据链路层 物理层
TCP/IP 4层 应用层 传输层 网络层 物理层–》在使用

1.2 IP地址–》网络地址

定义:在网络中唯一标识一台主机符号就是IP地址(唯一标识一台主机的符号是MAC地址)
ipv4维护IP地址
4:1 IP协议的版本号是V4
2 IPV4协议维护的IP地址宽度是4byte=32bit
ipv4协议提供了2^32个IP地址,将这些地址分成了5类:
A 1.0.0.1~126.255.255.254
B 127.0.0.1~191.255.255.254
C 192.0.0.1~223.255.255.254 -->用户IP地址 24网络号+8主机号
D 224.0.0.1~239.255.255.254–》组播地址
E 240.0.0.1~255.255.255.254–>保留地址
unsigned int addr=inet_addr(“127.0.0.1”);

1.3 网络协议

定义:在网络通信中对某种通信规则的约定
分类:1 网络通用协议(TCP/IP协议族)
2 行业内部专有协议
3 自定义协议

1.4 端口号

作用:用作标识一个应用进程
是一个unsigned int 的整数,表示范围1-65535
1-1023已被著名的协议或程序占用,用户可用:1024~65535

1.5 字节序

主机字节序:是不同的CPU主机存贮多字节整数的方式,有大端主机字节序,有小端主机字节序
大端主机字节序:将数据的高字节存放在内存的低地址上
小端主机字节序:将数据的高字节存放在内存的高地址上
注意:由于网络通信中两台主机的字节序有可能不同,会造成发送的数据和接收的数据反序,所以在传送网络数据前要做字节适配处理,将多字节整数从主机字节序转换成网络字节序
网络字节序:是大端字节序,用于兼容通信双方的字节序
htonl:将4字节的数据的主机字节序转换成网络字节序
htons:将2字节的数据的主机字节序转换成网络字节序

2 基于TCP协议网络客户端&服务端模型

服务端:socket–>bind–>listen–>accept–>IO函数(read/write recv/send)
客户端:socket–>connect–>IO函数

 struct sockaddr      linux系统头文件中
		struct sockaddr--->16byte
  		{
    		__SOCKADDR_COMMON (sa_);	2byte
   		 char sa_data[14];		14byte
  		};

	#define	__SOCKADDR_COMMON(sa_) \
  	sa_family_t  sa_family;

	
	struct sockaddr_in-->16byte
  	{
   	 __SOCKADDR_COMMON (sin_); 2byte
   	 in_port_t sin_port; 2byte			
    	struct in_addr sin_addr;	 4byte	
   	 unsigned char sin_zero[sizeof (struct sockaddr) -
			   __SOCKADDR_COMMON_SIZE -
			   sizeof (in_port_t) -
			   sizeof (struct in_addr)];  8byte
  	};

	int socket(int domain, int type, int protocol);
		作用:创建一个用于通信的网络套接字
		参数1:协议域 AF_INET(ipv4协议)
		参数2:套接字类型 SOCK_STREAM  
		参数3:需要的其他协议 0--》自动匹配其他必要协议
		返回值:失败 -1  
       			   成功 标识socket通道的文件描述符 >3
    
   int bind(int sockfd, const struct sockaddr *addr,
                socklen_t addrlen);
		作用:给socket通道绑定网络接收终端
		参数1:文件描述符  socket的返回值
		参数2:表示本机地址信息的结构体指针
		参数3:地址结构体的长度
		返回值:0 成功  -1 失败

  int listen(int sockfd, int backlog);
		作用:监听客户端的连接请求
		参数1:文件描述符 socket的返回值
		参数2:服务端一次最大监听的客户端个数
		返回值:0 成功 -1 失败

   int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
		作用:接收客户端的连接请求
		参数1:文件描述符 socket的返回值
		参数2:地址信息结构,用来存放接收到的客户端的地址信息
		参数3:存放第二个参数大小的变量的地址
		返回值:成功 返回新的文件描述符--》标识一个新的socket通道--》用于收发数据,失败 -1
   ssize_t recv(int sockfd, void *buf, size_t len, int flags);
		作用:接收socket通道中的数据
		参数1:新的文件描述符 是accept的返回值
		参数2:本地接收buf
		参数3:期望接收的字节数
		参数4:是否阻塞的接收的标志 0表示阻塞接收
		返回值:>0 成功接收到的子节数
					-1 失败
   ssize_t send(int sockfd, const void *buf, size_t len, int flags);
		作用:往socket通道中发送数据
		参数1:新的文件描述符 是accept的返回值
		参数2:本地发送buf
		参数3:期望发送的字节数
		参数4:是否阻塞的发送的标志 0表示阻塞发送
		返回值:成功 返回发送的字节数
					失败 -1
   int connect(int sockfd, const struct sockaddr *addr,
                   socklen_t addrlen);
		作用:连接服务端
		参数1:文件描述符 socket的返回值
		参数2:目标服务器的主机地址信息结构
		参数3:第二个参数的长度
		返回值:0 成功  -1 失败

day2:

1 基于udp协议的网络客户端和服务端模型

	服务端:socket-->bind-->IO函数(sendto/recvfrom)
	客户端:socket-->IO函数(sendto/recvfrom)
	ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                    struct sockaddr *src_addr, socklen_t *addrlen);
	参数1:文件描述符
	参数2:接收buf
	参数3:期望接收的字节数
	参数4:阻塞或非阻塞标志 0--》阻塞
	参数5:用来保存对方地址信息
	参数6:参数5的长度的地址
	返回值:成功  期望接收到的字节数 失败 -1
	ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                  const struct sockaddr *dest_addr, socklen_t addrlen);
	参数1:文件描述符
	参数2:发送buf
	参数3:期望发送的字节数
	参数4:阻塞或非阻塞标志 0--》阻塞
	参数5:用来存放对方地址信息
	参数6:参数5的长度
	返回值:成功 期望发送的字节数  失败 -1

总结:TCP协议的通信模型&UDP协议的通信模型

	TCP是一个可靠的,全双工的,有序的,面向链接的字节流通信的协议。
为什么可靠:
1.丢失的数据包重发	(能保证拿到数据)
2.错误的数据包重发 	(保证能拿到正确的数据)
3.数据的有序到达(因为对每个数据包进行了编号)(拆包,编号)
4.有较为健全的校验机制(为了保证数据的正确性)
5.支持面向连接(保证通信线路的畅通)-->三次握手
6.有信道拥堵控制(通过一种对于信道拥堵解决的方案,来提高转发效率)	
产生的原因,是中继设备中(接收的速度 >> 发送的速度)

为什么有序(有序列号):
1.保证数据都能传输给对端,不至于当传输的数据 > 信道带宽
,导致数据丢弃。
2.通过序号,在对端主机上可以拼接成原本的数据包
3.保证数据传输的可靠性
如何面向链接:
三次握手和四次挥手

UDP:
UDP(The User Datagram Protocol):无连接的数据报协议,别名"不可靠的协议"
<1>使用校验和来实现错误侦测
<2>UDP常用于媒体流的传输(音频、视频、等),在这种情况下,实时性比
可靠性更重要
<3>UDP也常用于简单的查询/回应程序,例如DNS查找,在这种情况下,
建立可靠传输的资源消耗太大
<4>UDP是一种实时传输协议(Real-time Transport Protocol),这种协议
通常用来传输实时数据例如:音视频流

不可靠的原因:
1.非面向连接(不关心接收端是否在线)–》没有三次握手
2.丢包不重发
3.错误的包不重发
4.没有信道拥堵控制
5.有一个最大传输长度限制
6.没有严格的校验机制
问题:使用UDP通信模型,如何保证发送数据相对可靠性?可以采用重传机制
如何抉择使用TCP还是UDP
1.可靠性
2.实时性
可靠性 > 实时性: TCP
可靠性 < 实时性: UDP
tcp/udp是传输层的两个协议,他们的区别是:
tcp:是面向连接的可靠的传输协议
udp:是面向无连接的不可靠的传输协议
常见套接字类型:

流式套接字(SOCK_STREAM)

提供了一个面向连接、可靠的数据传输服务,数据无差错、无重复的发送且按发送顺序接收。内设置流量控制,避免数据流淹没慢的接收方。数据被看作是字节流,无长度限制。

数据报套接字(SOCK_DGRAM)

提供无连接服务。数据包以独立数据包的形式被发送,不提供无差错保证,数据可能丢失或重复,顺序发送,可能乱序接收。
原始套接字(SOCK_RAW)–ping.c可以对较低层次协议如IP、ICMP直接访问

2 IO模型

linux 系统提供了4种IO模型:

2.1阻塞IO

若要读的数据没有准备好,或要写入的目标没有空间,将会发生读写阻塞
阻塞函数:优点:一直等待结果,直到等到结果
缺点:如果等待的接收数据的通道坏掉或文件损坏,那么当前进程会一直被挂起

2.2非阻塞IO

若要读的数据没有准备好,IO函数返回一个约定的错误值,不阻塞当前进程,可以通过循环去多次尝试读取数据。
非阻塞函数:优点:没有读到数据不阻塞当前进程,而是直接返回,带回一个错误值
2缺点:多次调用系统调用函数会有极大的系统资源开销。

2.3IO多路复用

思想:分三步
1 构建一个文件描述符集合表,表的大小是1024bit位,每一个bit表示一个文件描述符所对应的IO通道上是否有数据发生(或者IO通道是否活跃?)?如果有数据发生,该bit位为1,其他bit位被置位0。
2 使用select函数监控制定范围的文件描述符所对应的IO通道是否有数据发生,如果有数据发生,该函数返回通道的个数,并且将文件描述符集合表的相应bit置位1,同时将其他bit置位0,如果没有数据发生,那么select将阻塞当前进程。
3 对文件描述符集合表中的置位结果做出相应的判断,使用FD_ISSET判断该文件描述符在描述符集合表中是否为1,如果为1,响应这路IO数据,否则不处理。

分析:1 文件描述符集合表–》文件描述符对应的IO通道是否有数据发生
fd_set stFdr;1024bit
2 select 监控 置位–》stFdr
3 对stFdr中的置位情况做判断 0–>fgets 3–》accept 4–>recv/send

	 int select(int nfds, fd_set *readfds, fd_set *writefds,
              fd_set *exceptfds, struct timeval *timeout);
		作用:监控文件描述符对应的IO通道是否有数据发生
		参数1:要监控的文件描述符的最大个数
		参数2:读文件描述符集合表
		参数3:写文件描述符集合表
		参数4:异常文件描述符集合表
		参数5:超时时间 ,若为NULL,表示将select变成阻塞函数
		返回值:成功 有数据发生的通道的个数 
				  失败 -1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值