一.网络基础
一.网络体系结构:
定义:指网络的分层模型和每层所使用的协议的集合
有两种体系结构:OSI和TCP/I
1.OSI:OSI模型把网络设备分成了7层:
1.应用层,FTP(文件传输),telnet(远程登陆)
2.表示层:数据格式定义、数据转换/加密
3.会话层:建立通信进程的逻辑名字与物理名字之间的联系
4.传输层:差错处理/恢复,流量控制,提供可靠的数据传送
5.网络层:数据分组、路由选择
6.数据链路层:数据组可发送、接收的帧
7.物理层:传输物理信号,接口信号形式、速率
----------理想化的模型
2.TCP/IP四层模型:
----------实际使用
对于以上两种模型来说,除了物理层没有协议,其他层都有对应的协议去完成该层相应的功能
二.ip地址
- 定义
IP地址:在网络中唯一标识一台主机的符号
MAC地址(硬件地址):唯一标识一台主机的符号
cmd 中 查看自己ip地址:ipconfig linux下:ifconifg
一台主机的物理地址是固定的,而ip地址是不固定的,ip分配的
- ipv4
现在使用的ip地址是ipv4 协议维护的地址
ipv4维护的ip地址宽度是四个字节
4个字节的ip地址可表示的地址范围是:
0000 0000*4-1111 1111*4
可以分成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地址
D类:224.0.0.1-239.255.255.254 组播&多播地址
E类:240以后
c类=24bit网络号+8bit主机号
理论能接2^8=256台主机 实际上能接253台 256或者0或者1不能用
子网掩码:255.255.255.0
作用:相与判断是内网还是外网
3.网络协议
1.定义:通信双方对某种通信规则的约定
2..协议:
(1)通用的网络协议 TCP/IP协议栈(封装在os)
(2)行业内部专用的网络协议 协议开发
(3)用户自定义协议 产品
3.常用协议
- 作用:用端口号区分应用进程
- 端口号是一个无符号的整数,范围1-65535
(1)1-1023 众所周知端口号,已经被占用
- 自定义从1024开始到65535
5.字节序
- 主机字节序
(1)不同的cpu主机存储多字节的整数方式,有大端序和小端序
大端序主机:数据的高字节存放在内存的低地址
小端序主机:数据的高字节存放在内存的高地址
主机字节序转化为网络字节序
htonl
htons
(2)多字节整数发送前要从主机字节序转化成网络字节序,以适配对端的网络主机
- 网络字节序
网络字节序:大端序
二.基于TCP协议的网络客户端和服务器模型
五个步骤:
socket --->bind---->listen--->accept---->IO函数
- socket 创建套接字
socket作用:创建一个用于通信的网络软通道
int socket(int domain,int type,int protoco)
参数:1.地址族
2.套接字类型
SOCK_STREAM流式套接字
SOCK_DGRAM 数据报套接字
3.通常为0:自动匹配其他类型的协议
返回值:正确返回文件描述符 为3(因为系统已经自动打开了3个文件描述符,标准输入,标准输出,错误信息)文件描述符3(用于连接客户端),错误返回-1,
- bind 绑定本机的地址和端口
struct sockaddr_in stserver;
stserver.sin_family=AF_INIT;
stserver.sin_port=honts(8888);
stserver.sin_addr.s_addr=inet_addr(“127.0.0.1”);
inet_addr();数值转换为32位无符号
0.0.0.0 万能地址
int bind(int sockfd,struct sockaddr*addr,int addrLen)
参数:1.套接字的返回值
2.指向定义好的目标信息结构体
3.第二个参数的长度
返回值:成功返回0,失败-1
- listen 侦听服务端有没有连
listen(int sockfd,int backlog);
参数:1.文件描述符(监听连接的套接字)
2.最多能侦听多少个服务端
返回值:成功返回0,失败-1
- accept 接受客户端
int accept(int sockfd,struct sockaddr*addr,socklen_t*addrlen)
参数 1:监听的套接字
2. .用来存放对方的地址信息
3..地址长度的信息
返回值:成功返回新的文件描述符(新的网络软通道)用于下一步收发数据,失败-1
- recv/send 收发数据
ssize_t recv()
函数参数:
1.客户端接收的文件描述符(新的)
2.准备好的数据
3.接收大小
4.阻塞0非阻塞1
函数返回值:已经接收到的字节个数,失败-1
send
函数参数:
- 文件描述符
- 提前准备好的数据
- 大小
- 阻塞0或非阻塞1
函数返回值:成功返回成功发送的字节个数,失败-1
注意:测一次的话最后关闭
- 客户端
socket--->connect--->IO函数
1.socket 创建套接字
int socket(int domain,int type,int protoco)
参数:1.协议域
2.套接字类型
SOCK_STREAM流式套接字
SOCK_DGRAM 数据报套接字
3.通常为0:自动匹配其他类型的协议
返回值:正确返回,错误返回-1,
2.connect 建立连接
函数参数:
1.文件描述符(socket的返回值)
2.服务端的地址信息
3.结构体的大小
函数返回值:成功返回0,失败-1
客户端只有一个通道,服务端两个
send
函数参数:
1.文件描述符
2.提前准备好的数据
3.大小
4.阻塞0或非阻塞1
函数返回值:成功返回成功发送的字节个数,失败-1
ssize_t recv()
函数参数:
1.客户端接收的文件描述符(新的)
2.准备好的数据
3.接受大小
4.阻塞0非阻塞1
函数返回值:已经接收到的字节个数,失败-1
注意:测一次的话最后关闭
##所有系统头文件
linux下的头文件在:/usr/include
- 基于UDP协议的客户端和服务器模型
1.服务端:socket--->bind-->I函数(recvfrom/sendto)
- socket 创建套接字
- bind
INADDR_ANY 这个宏表示
- recvfrom/sendto 收发
5.对方的地址信息,6.地址长度
5.对方的地址信息 6.长度sizeof
2.客户端:socket-->IO函数(sendto/recvfrom)
1.socket
2.sendto
两种网络编程框架的对比
1.TCP:使用了流式套接字(SOCK_STREAM)
1.提供一个面向连接、可靠的数据传输服务,数据无差错、无重复的发送且按照发送顺序接收。内部设置了流量控制,避免数据流淹没满的接收方。数据被看作是字节流,无长度限制。
2.协议
TCP(传输控制协议):
TCP 是一个可靠的,全双工的,有序的,面向链接的字节流通信的协议。
为什么可靠:
1.丢失的数据包重发(能保证拿到数据)
2.错误的数据包重发 (保证能拿到正确的数据)
3.数据的有序到达(因为对每个数据包进行了编号)(拆包,编号)
4.有较为健全的校验机制(为了保证数据的正确性)
5.支持面向连接(保证通信线路的畅通)-->三次握手
6.有信道拥堵控制(通过一种对于信道拥堵解决的方案,来提产生的原因,是中继设备中(接收的速度 >> 发高转发效率)送的速度)
为什么有序(有序列号):
1.保证数据都能传输给对端,不至于当传输的数据>信道
带宽,导致数据丢弃。
2.通过序号,在对端主机上可以拼接成原本的数据包
3.保证数据传输的可靠性
2.UDP:使用了数据报套接字(SOCK_DGRAM)
1.提供了无连接服务。数据包以独立数据包的形式被发送,不提供无差错保证,数据可能丢失或者重复,顺序发送,可能会乱序接收。
2.UDP(The User Datagram Protocol):无连接的数据报协议,别名"不可靠的协议"
<1>使用校验和来实现错误侦测
<2>UDP常用于媒体流的传输(音频、视频、等), 在这种情况
下,实时性比
可靠性更重要
<3>UDP也常用于简单的查询/回应程序,例如DNS查找,在
这种情况下,建立可靠传输的资源消耗太大
<4>UDP是一种实时传输协议(Real-time Transport Protocol),这
种协议通常用来传输实时数据例如:音视频流
不可靠的原因:
1.非面向连接(不关心接收端是否在线-)--》没有三次握手
2.丢包不重发
3.错误的包不重发
如何抉择使用 TCP 还是 UDP?
1.可靠性
2.实时性
可靠性 > 实时性:TCP
可靠性 < 实时性: UDP
补充:原始套接字(SOCK_RAM)--ping.c
可以对较低层次协议如IP,ICMP直接访问
三.IO模型
1.在UNIX/linux下主要有4种I/O模型:
1.阻塞I/O:send/recv sendto/recvfrom
最常用、最简单、效率最低
2.非阻塞I/O:
可防止可防止进程阻塞在I/O操作上,需要轮询
3.I/O 多路复用:
允许同时对多个I/O进行控制
4.信号驱动(异步)I/O:
一种异步通信模型
2.常见的阻塞I/O函数:
recv, recvfrom ,read, write, send, accept, connect,
3.非阻塞I/O函数:
非阻塞的标志 :O_NONBLOCK
常见的非阻塞IO函数:read/write(可以通过修改底层驱动设计成非阻塞)
4.多路复用I/O
基本思想:
1.先构造一张有关描述符的表,然后调用一个函数。当这些文件描述符中的一个或多个已准备好进行IO时函数才返回。
2.函数返回时告诉进程那个描述符已就绪,可以进行I/O操作。
步骤:
1.构建一张文件描述符集合表,表的大小为1024bit,这些bit位分别对应了1024个文件描述符,这些bit位中存放的数据表示的是该描述符对应的IO通道是否有数据发生,1表示有数据,0表示没有数据。
int a[32]--->
2.调用一个监测函数select ()监测程序的文件描述符对应的通道是否有数据发生?如果有数据发生,将文件的描述文件符集合表的相应bit位置1,同时将其他位置的bit位置0,并返回监测到的文件描述符的通道个数。
int select(int n, fd_set *read_fds, fd_set *write_fds, fd_set *except_fds, struct timeval *timeout);
作用:监控文件描述符对应的IO通道是否有数据
参数:1. n :监控的最大通道个数
2.读文件描述符的集合表,也就是前面创建的
3.指向写文件描述符的集合表
4.指向异常文件描述符集合表
5.为0时,只检测文件描述符集合的状态。然后立即返回
为NULL时,函数阻塞监控关注的文件描述符通道
为 一个时间时,时间到达之前select函数一直阻塞,时间到才结束监控
返回值:监控到的有数据发生的IO通道的个数,失败-1
3.对检测的结果做出判断和响应。
循环遍历文件描述符集合表中,查看集合表中关心的描述符对应的bit位是否是1,如果为1,响应这路IO,如果是0,继续循环。
int (FD_ISSET(0,stFdr))
{响应0对应的通道数据 fgets();}
atoi()
作用:将字符串转化为整形数