1 OSI参考模型 七层 ((目的是使不同的系统能够通信)
应用层 展示给用户。常见的协议:HTTP(超文本传输协议(基于TCP)),HTTPS(安全的超文本传输协议(基于TCP)443),DNS,FTP(多连接协议(基于TCP)21),TFTP(简单文件传输协议(基于UDP)),TELNET(23),SSH,(IMAP,SMTP(25),POP3(邮件协议(三个))),RIP(报文520)等。
表示层 使多个主机之间传送的信息能够互相理解,包括数据的压缩、加密格式转换等。
会话层 管理主机之间的会话过程,包括会话建立、终止和会话过程中的管理。
传输层 提供可靠的数据传输,监测路由器丢弃的包,然后产生重传请求,能够将乱序收到的包重新排序。TCP,UDP
网络层 单位是数据包 对子网之间的数据进行路由选择,分组和重组。属于本层的规范有:IP,IPX ,OSPF,ICMP,IGMP,ARP,RARP等。 路由器(识别IP) ,IP头的长度(20-60)
数据链路层 单位是帧 把物理层的比特流成帧,实现可靠的无差错数据传输。本层定义的规范有:SDLC,HDLC,PPP,STP,帧中继等。 交换机(识别MAC),以太网,网桥(是一种交换机)
物理层 单位是比特 提供物理介质,定义了所有电子及物理设备的规范,有RS-232(串口),RS-449,RJ-45等。 网卡
ARP 地址解析协议(IP--MAC)
RARP反向地址解析协议(MAC--IP)
ftp 就是下载 通过远程方式下载别人电脑上的东西(完成两台计算机之间的拷贝)
ICMP协议用于传递差错信息、事件、回显、网络信息等控制数据。Ping程序就是通过ICMP实现的。
Ping过程 主机A(192.168.1.150)想要和主机B(192.168.1.151)通信
①主机A pingB,ping 会判断是主机名还是IP,如果是主机名,先经过DNS域名解析协议把主机B转换成32位IP地址。知道IP但是不知道是哪一台主机(MAC地址)每台主机都有唯一的MAC地址,于是先在局域网内发送ARP请求广播,查找主机B的MAC地址;
②ping程序向目的IP地址发送一个ICMP的ECHO包,目的是回显目的IP的MAC地址(48位)也叫硬件地址;
③主机B的ARP协议层接收到主机A的ARP请求后,将本机的硬件地址填充到应答包,发送ARP应答到主机A,此时主机A接收到了B的MAC地址;
④主机A发送ICMP数据包到主机B,主机B接收到主机A的ICMP包,发送响应包;
⑤主机A接收到主机B的ICMP响应包。Ping过程结束。
3 ⑴封装
数据从上到下(应用层到数据链路层)传递的过程。
每层在传输的时候都会加上各自的头,
⑵解封装
数据从下到上(数据链路层到应用层)传递,去头。
⑶ UDP服务器 UDP客户端
1 socket()创建socket 设置socket属性 1 socket()创建socket 设置socket属性
2 bind() 绑定IP,端口等信息 2 sendto()发送数据到服务器
3 recvfrom()接收客户端数据 3 recvfrom()接收服务器应答
4 sendto()发送数据应答 4 关闭网络连接
5 关闭网络连接
TCP服务器 TCP客户端
1 socket()创建socket 设置socket属性 1 socket()创建socket 设置socket属性
2 bind() 绑定IP,端口等到socket上 2 bind() 绑定IP,端口等到socket上
3 listen()监听 3 connect()连接服务器
4 accept()接收客户端的连接 4 send() or recv() 收发数据
5 send() or recv() 收发数据 5 关闭网络连接
6 关闭网络连接
4 TCP特点
① 基于字节流
② 面向连接
③ 可靠传输
④ 缓存传输
⑤ 全双工
⑥ 流量控制 滑动窗口
5 TCP的6个标志位
URG紧急指针有效
ACK 确认序号有效
PSH 接收方应尽快将这个报文段交给应用层
RST 连接重置
SYN 同步序号用来发起一个连接
FIN 表示将要终止一个连接
6 TCP如何保证可靠
① 段
应用数据会被分割成TCP认为最适合发送的数据块称为段;
② 定时功能
当tcp发送一个段后,它启动一个定时器,等待目的端确认收到这个报文段,如果不能收到一个确认,重发这个报文段;
③ 校验和
当tcp收到来自tcp连接另一端的数据,他将发送一个确认,这个确认不立即发送。通常推迟n秒,tcp将保持它首部和数据的校验和,这是一个端到端的校验和,目的是监测数据在传输过程中的任何变化,如果收到段的校验和有差错,tcp将丢弃这个报文段并且不确认(导致对方超时重传)
④ 重新排序
tcp承载于ip数据报来传输,而ip数据报的到达可能会失序,因此tcp报文段的到达也可能会失序,tcp可以借助自身内部的算法,将收到的数据进行重新排序;
⑤ 重复丢弃
tcp接收端会把重复接收的数据丢弃;
⑥ 流量控制(滑动窗口)
在数据传输的过程中,tcp提供流量控制,tcp连接的每一方都有一定大小的缓冲空间,通过滑动窗口的形式传输数据;
7 ① TCP短连接
Client方与Server每进行一次报文收发交易时才进行通讯连接,交易完毕后立即断开连接。此种方式常用于一点对多点通讯,比如多个Client连接一个Server.
短连接的优点是:管理起来比较简单,存在的连接都是有用的连接,不需要额外的控制手段。
②TCP长连接
client向server发起连接,server接受client连接,双方建立连接。Client与server完成一次读写之后,它们之间的连接并不会主动关闭,后续的读写操作会继续使用这个连接。
如果一个给定的连接在两小时内没有任何的动作(通过设置socket属性为SO_KEEPALIVE。但是系统默认是设置的2小时的心跳频率。),则服务器就向客户发一个探测报文段,客户主机必须处于以下4个状态之一:
1. 客户主机依然正常运行,并从服务器可达。客户的TCP响应正常,而服务器也知道对方是正常的,服务器在两小时后将保活定时器复位。
2. 客户主机已经崩溃,并且关闭或者正在重新启动。在任何一种情况下,客户的TCP都没有响应。服务端将不能收到对探测的响应,并在75秒后超时。服务器总共发送10个这样的探测,每个间隔75秒。如果服务器没有收到一个响应,它就认为客户主机已经关闭并终止连接。
3. 客户主机崩溃并已经重新启动。服务器将收到一个对其保活探测的响应,这个响应是一个复位,使得服务器终止这个连接。
4. 客户机正常运行,但是服务器不可达,这种情况与2类似,TCP能发现的就是没有收到探查的响应。
③心跳检测
心跳包主要用于TCP长连接的保活和断线处理。一般的应用下,判定时间在30-40秒比较不错。通过设置socket属性为SO_KEEPALIVE。但是系统默认是设置的2小时的心跳频率。时间太久,所以一般都是手工设置,
心跳检测步骤:
1客户端每隔一个时间间隔发生一个探测包给服务器(一般30-40s)
2客户端发包时启动一个超时定时器
3服务器端接收到检测包,应该回应一个包
4如果客户机收到服务器的应答包,则说明服务器正常,删除超时定时器
5如果客户端的超时定时器超时,依然没有收到应答包,则说明服务器挂了
8 UDP特点
① 无连接
② 不可靠
③ 一般情况下UDP更加高效(头简单,无确认机制)
9 TCP状态迁移路线图
下面的文章按照client/server两条路线讲述TCP状态迁移路线图。
1. 连接建立
1)Client
当处于Closed状态的Client端调用socket函数创建套接字,并调用connect函数连接服务器时,connect的调用让Client端的socket处于SYN_SENT状态(此时客户端向服务器发送一个SYN请求),当Client端收到Server的确认和请求SYN后,回复Server一个SYN后,套接字处于ESTABLISHED阶段,此时双方的连接已经可以进行读写操作。
2)Server
当Server端调用socket函数创建监听套接字,调用bind操作,将监听套接字与指定的地址和端口关联,然后又调用listen函数,使得监听套接字状态处于LISTEN状态。
当Server端调用accept操作时,会从队列中取出一个client连接,同时在server这端会产生一个会话套接字,用于和client端套接字的通信,这个会话套接字的状态是ESTABLISH。
2. 连接关闭
Client主动关闭,Server被动关闭
当client想要关闭它与server之间的连接,首先client这边会首先调用close函数,client端会发送一个FIN到server端,client端处于FIN_WAIT1状态。当server端返回给client ACK后,client处于FIN_WAIT2状态,server处于CLOSE_WAIT状态。
当server端检测到client端的关闭操作(read返回为0),server端也需要调用close操作,server端会向client端发送一个FIN。此时server的状态为LAST_ACK,当client收到来自server的FIN后,client端的套接字处于TIME_WAIT状态,它会向server端再发送一个ack确认,此时server端收到ack确认后,此套接字处于CLOSED状态。
主动关闭的socket当收到对端的FIN操作后,该socket就会处于TIME_WAIT状态,处于TIME_WAIT状态的socket会存活2MSL(Max Segment Lifetime),之所以存活这么长时间是有理由的:
一方面是可靠的实现TCP全双工连接的终止,也就是当最后的ACK丢失后,被动关闭端会重发FIN,因此主动关闭端需要维持状态信息,以允许它重新发送最终的ACK。
另一方面TCP在2MSL等待期间,定义这个连接(4元组)不能再使用,任何迟到的报文都会丢弃。设想如果没有2MSL的限制,恰好新到的连接正好满足原先的4元组,这时候连接就可能接收到网络上的延迟报文就可能干扰最新建立的连接。
10 TCP和UDP的区别
①基于连接/无连接
TCP是端--端连接的,例如a—b—c—d—e,对于传输层来说它不知道bcd的存在,但需要a到e之间建立连接;而UDP是点—点的通信,不需要建立连接,例如a—b,b—c中间不会经过其他节点;
②可靠性
TCP是全双工的可靠通信,UDP不可靠,TCP的可靠析构主要表现在它是通过三次握手建立连接,四次回收释放连接,数据传输的时候,TCP会把数据分割成最合适的数据块,通过滑动窗口的形式发送,而且内部有校验和还会重新排序,而UDP只是尽最大努力交付;
③有序性
TCP以字节流的形式发送,TCP协议会按照一定的算法排好序,而UDP无序;
④数据边界
TCP是面向字节流,UDP是面向报文,数据流可以拆,数据报不可拆,TCP是等每一次缓冲区满的时候一次性把数据读出去,假如第一个包2K第二个包4K,那么它只是接收了一个大于6K的包而导致粘包,UDP不会粘包因为UDP每次接收一个包;
⑤速度
TCP慢,UDP快,因为TCP必须建立连接;
⑥头大小不同
TCP的头是20字节,包含源/目的端口号、TCP头部长度、TCP校验和,还有序列号、确认号,保留位等,而UDP头是8字节,只包含源/目的端口号、UDP头部长度、UDP校验和;
⑦ UDP可以进行组播和广播,TCP不可以;
⑧应用场合不同
TCP用在高可靠,并且对传输时间要求不高的地方,UDP则是用在需要传输速度快的应用领域。
11 TCP粘包的原因和解决办法
粘包出现原因:
1发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小、数据量小的数据,合并成一个大的数据块,然后进行封包发送到接收端,造成粘包;
2 接收方不及时接收缓冲区的包,造成多个包接收
解决办法:一是对于发送方引起的粘包现象,用户可通过编程设置来避免,TCP提供了强制数据立即传送的操作指令push,TCP软件收到该操作指令后,就立即将本段数据发送出去,而不必等待发送缓冲区满;或者封包;
封包
封包就是给一段数据加上包头,这样一来数据包就分为包头和包体两部分内容了(以后讲过滤非法包时封包会加入"包尾"内容)。包头其实上是个大小固定的结构体,其中有个结构体成员变量表示包体的长度,这是个很重要的变量,其他的结构体成员可根据需要自己定义。根据包头长度固定以及包头中含有包体长度的变量就能正确的拆分出一个完整的数据包。
二是对于接收方引起的粘包,则可通过优化程序设计、精简接收进程工作量、提高接收进程优先级等措施,使其及时接收数据,从而尽量避免出现粘包现象;
三是由接收方控制,将一包数据按结构字段,人为控制分多次接收,然后合并,通过这种手段来避免粘包。
12为什么UDP不粘包?
UDP,不会使用块的合并优化算法,这样,实际上目前认为,是由于UDP支持的是一对多的模式,所以接收端的skbuff(套接字缓冲区)采用了链式结构来记录每一个到达的UDP包,在每个UDP包中就有了消息头(消息来源地址,端口等信息),这样,对于接收端来说,就容易进行区分处理了。所以UDP不会出现粘包问题。
13 UDP丢包、无序
⑴主要丢包原因:
1、接收端处理时间过长导致丢包:调用recv方法接收端收到数据后,处理数据花了一些时间,处理完后再次调用recv方法,在这二次调用间隔里,发过来的包可能丢失。对于这种情况可以修改接收端,将包接收后存入一个缓冲区,然后迅速返回继续recv。
2、发送的包巨大丢包:虽然send方法会帮你做大包切割成小包发送的事情,但包太大也不行。例如超过50K的一个udp包,不切割直接通过send方法发送也会导致这个包丢失。这种情况需要切割成小包再逐个send。
3、发送的包较大,超过接受者缓存导致丢包:包超过mtu size数倍,几个大的udp包可能会超过接收者的缓冲,导致丢包。这种情况可以设置socket接收缓冲。以前遇到过这种问题,我把接收缓冲设置成64K就解决了。
int nRecvBuf=32*1024;//设置为32K
setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int));
4、发送的包频率太快:虽然每个包的大小都小于mtu size 但是频率太快,例如40多个mut size的包连续发送中间不sleep,也有可能导致丢包。这种情况也有时可以通过设置socket接收缓冲解决,但有时解决不了。所以在发送频率过快的时候还是考虑sleep一下吧。
5、局域网内不丢包,公网上丢包。这个问题我也是通过切割小包并sleep发送解决的。如果流量太大,这个办法也不灵了。总之udp丢包总是会有的,如果出现了用我的方法解决不了,还有这个几个方法: 要么减小流量,要么换tcp协议传输,要么做丢包重传的工作。
14