建立TCP服务器的各个系统调用
套接字层接收进行的任何 TCP 系统调用。套接字层验证 TCP 应用程序传递的参数的正确性。这是一个独立于协议 的层,因为尚未将协议连接到调用中。 协议层,该层包含协议的实际实现(本例中为 TCP)。当套接字层对协议层进行调用时,将确保对两个层之间共享的数据结构具有独占访问权限。这样做是为了避免任何数据结构损坏。 接口层:层从物理链路接收数据,并向物理链路传输数据。 每个套接字具有一个套接字队列,并且每个接口具有一个用于数据通信的接口队列。不过,对于整个协议层,只有一个称为 IP 输入队列的协议队列。接口层通过此 IP 输入队列将数据输入到协议层。协议层使用相应的接口队列将数据输出到接口。 socket所处层次
1.soket接口 参数: protofamily: 指协议族 so_type:指定socket的类型 protocol: 指定具体的协议 2.bind接口 功能:将创建的socket绑定到指定的IP地址和端口上,通常是第二个调用的socket接口。当socket函数返回一个描述符时,只是存在于其协议族的空间中,并没有分配一个具体的协议地址(这里指IPv4/IPv6和端口号的组合),bind函数可以将一组固定的地址绑定到sockfd上。 1.sockfd : 是调用socket()函数创建的socket描述符 2.addr :指明要绑定的本地IP和端口号,使用网络字节序,即大端模式 3.addrlen :表示addr的长度 4.返回值:0 – 成功,-1 – 出错。
通常服务器在启动的时候都会绑定一个众所周知的协议地址,用于提供服务,客户就可以通过它来接连服务器;而客户端可以指定IP或端口也可以都不指定,未分配则系统自动分配。这就是为什么通常服务器端在listen之前会调用bind(),而客户端就不会调用,而是在connect()时由系统随机生成一个。
3.listen接口 参数 sockfd:是调用socket()函数创建的socket描述符(套接字号) backlog:指定内核为此套接字维护的最大连接个数,该队列不能太长也不能没有,因为当队列太长时,需要耗费一定的资源进行维护和管理,没有的话也会降低操作系统的效率 功能
listen()函数仅被TCP类型的服务器程序调用,实现监听服务,它实现2件事情:
- 当socket()创建1个socket时,被假设为主动式套接字,也就是说它是一个将调用connect()发起连接请求的客户端套接字;函数listen()将套接口转换为被动式套接字,指示内核接受向此套接字的连接请求,调用此系统调用后tcp 状态机由close转换到listen。
- 第2个参数指定了内核为此套接字排队的最大连接个数
connect接口 功能: connect()通常由TCP类型客户端调用,用来与服务器建立一个TCP连接,实际是发起3次握手过程 参数: 1.sockfd – 本地客户端额socket描述符 2.serv_addr – 服务器协议地址; 3.addrlen – 地址缓冲区的长度
**注意:**1) 可以在UDP连接使用使用connect(),作用是在UDP套接字中记住目的地址和目的端口。 (2) UDP套接字使用connect后,如果数据报不是connect中指定的地址和端口,将被丢弃。没有调用connect的UDP套接字,将接收所有到达这个端口的UDP数据报,而不区分源端口和地址。
accept接口: 仅被TCP类型的服务器程序调用,从已完成连接队列返回下一个建立成功的连接,如果已完成连接队列为空,线程进入阻塞态睡眠状态 参数: 1.sockfd – socket()函数返回的描述符 2.输出的一个sockaddr_in变量地址,该变量用来存放发起连接请求的客户端的协议地址; 3.addrten – 作为输入时指明缓冲器的长度,作为输出时指明addr的实际长度
注意: 如果accpet()执行成功,返回由内核自动生成的一个全新socket描述符,用它引用与客户端的TCP连接。通常我们把accept()第一个参数称为监听套接字(listening socket),把accept()功能返回值作为已连接套接字(connected socket)。一个服务器通常只有1个监听套接字,监听客户端的连接请求;服务器内核为每一个客户端的TCP连接维护1个已连接套接字,用它实现数据双向通信。
listen、connect、accept的执行流程
(1)服务器端在调用listen之后,内核会建立两个队列,SYN队列和ACCEPT队列,其中ACCPET队列的长度由backlog指定。 (2)服务器端在调用accpet之后,将阻塞,等待ACCPT队列直到有元素。 (3)客户端在调用connect之后,将开始发起SYN请求,请求与服务器建立连接,此时称为第一次握手。 (4)服务器端在接受到SYN请求之后,把请求方放入SYN队列中,并给客户端回复一个确认帧ACK,此帧还会携带一个请求与客户端建立连接的请求标志,也就是SYN,这称为第二次握手 (5)客户端收到SYN+ACK帧后,connect返回,并发送确认建立连接帧ACK给服务器端。这称为第三次握手 (6)服务器端收到ACK帧后,会把请求方从SYN队列中移出,放至ACCEPT队列中,而accept函数也等到了自己的资源,从阻塞中唤醒,从ACCEPT队列中取出请求方,重新建立一个新的sockfd,并返回。
send函数接口 功能:主要是进行TCP类型的数据发送 参数: 1.sockfd – 发送端套接字描述符(非监听描述符) 2.msg – 待发送数据的缓冲区 3.len – 待发送数据的字节长度 4.flags – 一般情况下置为0 recv() 功能:主要用于TCP类型的数据接收 参数: 1.sockefd – 接收端套接字描述符(非监听描述符) 2.buf – 接收缓冲区的基地址 3.len – 以字节计算的接收缓冲区长度 4.flags – 一般情况下置为0
注: 阻塞模式:recv/recvfrom将会阻塞到缓冲区里至少有一个字节(TCP)/至少有一个完整的UDP数据报才返回,没有数据时处于休眠状态。 非阻塞模式:则立即返回,有数据则返回拷贝的数据大小,否则返回错误-1
说明socket网络编程有哪些系统调用?其中close是一次就能直接关闭的吗,半关闭状态是怎么产生的?
socket() 创建套接字
bind() 绑定本机端口
connect() 建立连接 (TCP三次握手在调用这个函数时进行) listen() 监听端口 accept() 接受连接 recv(), read(), recvfrom() 数据接收 send(), write(), sendto() 数据发送 close(), shutdown() 关闭套接字 close() /shutdown() 调用 close()/closesocket() 函数意味着完全断开连接,即不能发送数据也不能接收数据 但有些特殊时刻,需要只断开一条数据传输通道,而保留另一条。使用 shutdown() 函数可以达到这个目的:int shutdown(int sock, int howto); //Linux
close()/closesocket()和shutdown()的区别 close() / closesocket() 用来关闭套接字,将套接字描述符(或句柄)从内存清除,之后再也不能使用该套接字 shutdown() 用来关闭连接,而不是套接字,不管调用多少次 shutdown(),套接字依然存在,直到调用 close() / closesocket() 将套接字从内存清除。 默认情况下,close()/closesocket() 会立即向网络中发送FIN包,不管输出缓冲区中是否还有数据,而shutdown() 会等输出缓冲区中的数据传输完毕再发送FIN包
当一个进程向某个已收到RST的套接字执行写操作时,(此时写操作返回EPIPE错误)内核向该进程发送一个SIGPIPE信号,该信号的默认行为是终止进程,因此进程必须捕获它以免不情愿地被终止; 当一个进程向某个已收到RST的套接字执行读操作时,(此时读操作返回ECONNRESET错误
**TCP连接与断开详解(socket通信) ** tcp:数据包
连接简历的三次握手:(使用 connect() 建立连接时,客户端和服务器端会相互发送三个数据包)
客户端调用 socket() 函数创建套接字后,因为没有建立连接,所以套接字处于CLOSED状态;服务器端调用 listen() 函数后,套接字进入LISTEN状态,开始监听客户端请求。
1.当客户端调用 connect() 函数后,TCP协议会组建一个数据包,并设置 SYN 标志位,表示该数据包是用来建立同步连接的。同时生成一个随机数字 1000,填充“序号(Seq)”字段,表示该数据包的序号。完成这些工作,开始向服务器端发送数据包,客户端就进入了SYN-SEND状态。 2.服务器端收到数据包,检测到已经设置了 SYN 标志位,就知道这是客户端发来的建立连接的“请求包”。服务器端也会组建一个数据包,并设置 SYN 和 ACK 标志位,SYN 表示该数据包用来建立连接,ACK 用来确认收到了刚才客户端发送的数据包。 服务器生成一个随机数 2000,填充“序号(Seq)”字段。2000 和客户端数据包没有关系。 服务器将客户端数据包序号(1000)加1,得到1001,并用这个数字填充“确认号(Ack)”字段。 服务器将数据包发出,进入SYN-RECV状态。 3.客户端收到数据包,检测到已经设置了 SYN 和 ACK 标志位,就知道这是服务器发来的“确认包”。客户端会检测“确认号(Ack)”字段,看它的值是否为 1000+1,如果是就说明连接建立成功。接下来,**客户端会继续组建数据包,并设置 ACK 标志位,**表示客户端正确接收了服务器发来的“确认包”。同时,将刚才服务器发来的数据包序号(2000)加1,得到 2001,并用这个数字来填充“确认号(Ack)”字段。 客户端将数据包发出,进入ESTABLISED状态,表示连接已经成功建立。 4.服务器端收到数据包,检测到已经设置了 ACK 标志位,就知道这是客户端发来的“确认包”。服务器会检测“确认号(Ack)”字段,看它的值是否为 2000+1,如果是就说明连接建立成功,服务器进入ESTABLISED状态。
三次握手的关键是要确认对方收到了自己的数据包,这个目标就是通过“确认号(Ack)”字段实现的
**为了完成数据包的重传,TCP套接字每次发送数据包时都会启动定时器,如果在一定时间内没有收到目标机器传回的 ACK 包,那么定时器超时,数据包会重传。 **
重传超时时间(RTO, Retransmission Time Out) 最好是RTT(受制于网络距离与瞬态时延变化,所以实际上使用自适应的动态算法) 往返时间(RTT,Round-Trip Time)表示从发送端发送数据开始,到发送端收到来自接收端的 ACK 确认包(接收端收到数据后便立即确认),总共经历的时延。
重传次数 TCP数据包重传次数根据系统设置的不同而有所区别。有些系统,一个数据包只会被重传3次,如果重传3次后还未收到该数据包的 ACK 确认,就不再尝试重传。
下图演示了客户端主动断开连接的场景:
建立连接后,客户端和服务器都处于ESTABLISED状态。这时,客户端发起断开连接的请求:
1.客户端调用 close() 函数后,向服务器发送 FIN 数据包,进入FIN_WAIT_1状态 2**.服务器收到数据包后,检测到设置了 FIN 标志位,知道要断开连接,于是向客户端发送“确认包”,进入CLOSE_WAIT状态**。 3.客户端收到“确认包”后进入FIN_WAIT_2状态,等待服务器准备完毕后再次发送数据包。 4.等待片刻后,服务器准备完毕,可以断开连接,于是再主动向客户端发送 FIN 包,告诉它我准备好了,断开连接吧。然后进入LAST_ACK状态。 5.客户端收到服务器的 FIN 包后,再向服务器发送 ACK 包,告诉它你断开连接吧。然后进入TIME_WAIT状态。 6.服务器收到客户端的 ACK 包后,就断开连接,关闭套接字,进入CLOSED状态。
关于TIME_WAIT状态说明 ** 客户端最后一次发送 ACK包后进入 TIME_WAIT 状态,而不是直接进入 CLOSED 状态关闭连接,这是为什么呢?**
客户端最后一次向服务器回传ACK包时,有可能会因为网络问题导致服务器收不到,服务器会再次发送 FIN 包,如果这时客户端完全关闭了连接,那么服务器无论如何也收不到ACK包了,所以客户端需要等待片刻、确认对方收到ACK包后才能进入CLOSED状态。 数据包在网络中是有生存时间的,超过这个时间还未到达目标主机就会被丢弃,并通知源主机。这称为报文最大生存时间(MSL,Maximum Segment Lifetime)。TIME_WAIT 要等待 2MSL 才会进入 CLOSED 状态。ACK 包到达服务器需要 MSL 时间,服务器重传 FIN 包也需要 MSL 时间,2MSL 是数据包往返的最大时间,如果 2MSL 后还未收到服务器重传的 FIN 包,就说明服务器已经收到了 ACK 包。
对路由协议的了解与介绍。内部网关协议IGP包括RIP,OSPF,和外部网关协议EGP和BGP.
RIP“路由信息协议(Route Information Protocol)”的简写,主要传递路由信息,通过每隔30秒广播一次路由表,维护相邻路由器的位置关系,同时根据收到的路由表信息使用动态规划的方式计算自己的路由表信息。RIP是一个距离矢量路由协议,最大跳数为16跳,16跳以及超过16跳的网络则认为目标网络不可达。 OSPF:工作过程:邻居发现、路由交换、路由计算、路由维护
..................还有 EGP 和 BGP 没有补充
为什么使用三次握手,两次握手可不可以 如果使用两次握手的话,三次握手中的最后一次缺失,服务器不能确认客户端的接收能力。
1.情况一会伪造大量SYN请求发送给服务器,服务器立即确认并建立连接,分配资源,但是这一系列连接并不是真实存在的,这大大浪费了服务器的资源并且阻塞了正常用户的连接,这种也叫SYN洪泛 2.情况二服务器返回给客户端的ACK数据包可能会在传输的过程中丢失,而客户端没有收到该ACK数据包而拒绝接收服务器接下来发送的数据,于是服务器一直在发送,客户端一直在拒绝,形成死锁。
TIME_WAIT的意义
原因一但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。如果客户端发送的ACK发生丢失,服务器会再次发送FIN报文给客户端,所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。 原因二处理延迟到达的报文 由于路由抖动,TCP报文会延迟到达,为了避免延迟到达的TCP报文,被误认为是新的TCP链接,则应在允许创建新TCP前保持一个不可用状态,等待所有延迟报文小时 TCP怎么保证可靠性 1.校验和 2.确认应答+序列号 3.超时重传作者: TCP连接的每一方都有固定大小的缓冲空间,TCP的接收端只允许发送端发送接收端缓冲区能接纳的数据。当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失。TCP使用的流量控制协议是可变大小的滑动窗口协议。接收方有即时窗口(滑动窗口),随ACK报文发送 4.流量控制 5.拥塞控制当网络拥塞时,减少数据的发送。 发送方有拥塞窗口,发送数据前比对接收方发过来的即使窗口,取小 慢启动、拥塞避免、快速重传、快速恢复 流量控制的介绍,采用滑动窗口会有什么问题(死锁可能,糊涂窗口综合征) 所谓流量控制就是让发送方发送速率不要过快,让接收方来得及接收。利用TCP报文段中的窗口大小字段来控制发送方的发送窗口不大于接收方发回的窗口大小就可以实施流量控制。 ** 考虑一种特殊的情况**,就是接收方若没有缓存足够使用,就会发送零窗口大小的报文,此时发送放将发送窗口设置为0,停止发送数据。之后接收方有足够的缓存,发送了非零窗口大小的报文,但是这个报文在中途丢失的,那么发送方的发送窗口就一直为零导致死锁。 ** 解决:TCP为每一个连接设置一个持续计时器(persistence timer)。只要TCP的一方收到对方的零窗口通知,就启动该计时器,周期性的发送一个零窗口探测报文段。对方就在确认这个报文的时候给出现在的窗口大小(注意:TCP规定,即使设置为零窗口,也必须接收以下几种报文段:零窗口探测报文段、确认报文段和携带紧急数据的报文段)。 ** tcp滑动窗口协议 数据分类: 发送端
- Sent and Acknowledged:这些数据表示已经发送成功并已经被确认的数据
- Send But Not Yet Acknowledged:这部分数据称为发送但没有被确认,数据被发送出去,没有收到接收端的ACK,认为并没有完成发送,这个属于窗口内的数据
- Not Sent,Recipient Ready to Receive:这部分是尽快发送的数据,这部分数据已经被加载到缓存中,也就是窗口中了,等待发送,其实这个窗口是完全有接收方告知的,接收方告知还是能够接受这些包,所以发送方需要尽快的发送这些包
- Not Sent,Recipient Not Ready to Receive: 这些数据属于未发送,同时接收端也不允许发送的,因为这些数据已经超出了发送端所接收的范围 接收端: 1.Received and ACK Not Send to Process:这部分数据属于接收了数据但是还没有被上层的应用程序接收,也是被缓存在窗口内 2.Received Not ACK: 已经接收并,但是还没有回复ACK,这些包可能输属于Delay ACK的范畴了 3.Not Received:有空位,还没有被接收的数据
发送端: 发送窗口和可用窗口: 滑动窗口原理: TCP并不是每一个报文段都会回复ACK的,可能会对两个报文段发送一个ACK,也可能会对多个报文段发送1个ACK【累计ACK】 ** 拥塞控制和流量控制的区别** 拥塞控制:防止过多的数据注入到网络中,导致网络发生拥塞; 流量控制防止发送方一下子发送过多的数据到接收方,导致接收方缓存放不下。两种算法都是对发送方的行为进行控制的
TCP拥塞控制,算法名字?(极其重要)
慢启动、拥塞避免,快速重传和快速恢复 发送方维持一个拥塞窗口 cwnd ( congestion window )的状态变量。拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化。发送方让自己的发送窗口等于拥塞窗口和接受窗口的较小值。
1.慢启动。慢启动算法的思路是当主机开始发送数据时,先以比较小的拥塞窗口进行发送,然后每次翻倍,也就是说,由小到大逐渐增加拥塞窗口的大小,而这个大小是指数增长的 2.拥塞避免:拥塞避免算法的思路是让拥塞窗口cwnd缓慢地增大,即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1,而不是加倍。 3.快速重传当发送端连续收到三个重复的ack时,表示该数据段已经丢失,需要重发。此时慢启动阈值ssth变为原来一半,拥塞窗口cwnd变为ssth+3,然后+1+1的发(每一轮rtt+1) 4.快速恢复当超过设定的时间没有收到某个报文段的ack时,表示网络拥塞,慢启动阈值ssth变为原来一半,拥塞窗口cwnd=1,进入慢启动阶段 http协议与TCP的区别与联系
联系:Http协议是建立在TCP协议基础之上的,当浏览器需要从服务器获取网页数据的时候,会发出一次Http请求。Http会通过TCP建立起一个到服务器的连接通道,当本次请求需要的数据传输完毕后,Http会立即将TCP连接断开,这个过程是很短的。 区别HTTP和TCP位于不同的网络分层。TCP是传输层的协议,定义的是数据传输和连接的规范,而HTTP是应用层的,定义的是数据的内容的规范 建立一个TCP请求需要进行三次握手,而由于http是建立在tcp连接之上的,建立一个http请求通常包含请求和响应两个步骤 ** http/1.0和http/1.1的区别** HTTP 协议老的标准是 HTTP/1.0 ,目前最通用的标准是 HTTP/1.1 。HTTP1.0 只保持短暂的连接,浏览器的每次请求都需要与服务器建立一个 TCP 连接,但是最新的http/1.0加入了长连接,只需要在客户端给服务器发送的http报文头部加入Connection:keep-aliveHTTP 1.1 支持持久连接,默认进行持久连接,在一个 TCP 连接上可以传送多个 HTTP 请求和响应,减少了建立和关闭连接的消耗和延迟。 http的请求方法有哪些?get和post的区别(四种方法中只有POST不是操作幂等性的)) get 和 post区别 1.get方法不会修改服务器上的资源,它的查询是没有副作用的,而post有可能会修改服务器上的资源 2.get可以保存为书签,可以用缓存来优化,而post不可以 3.get把请求附在url上,而post把参数附在http包的包体中 4.浏览器和服务器一般对get方法所提交的url长度有限制,一般是1k或者2k,而对post方法所传输的参数大小限制为80k到4M不等 5.post可以传输二进制编码的信息,get的参数一般只支持ASCII
状态码:
200 - 请求成功
301 - 资源(网页等)被永久转移到其它URL
404 - 请求的资源(网页等)不存在
500 - 内部服务器错误
400 - 请求无效
403 - 禁止访问 http和https的区别,由http升级为https需要做哪些操作 HTTPS在HTTP的基础上加入了SSL协议,SSL依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。
区别 1.https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。 2.http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议 3.、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。 4.http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。 http->https切换 这里需要将页面中所有的链接,例如js,css,图片等等链接都由http改为https 通信: 1.客户使用https的URL访问Web服务器,要求与Web服务器建立SSL连接。 2.Web服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端。 3.客户端的浏览器与Web服务器开始协商SSL连接的安全等级,也就是信息加密的等级。 4.客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。 5.Web服务器利用自己的私钥解密出会话密钥。 6.Web服务器利用会话密钥加密与客户端之间的通信。 (注:服务器第一次传给客户端的公钥其实是CA对网站信息进行加密的数字证书,客户端的对称加密密钥其实是三个随机数的哈希(1. 客户端第一次给服务端发送请求时附带的随机数 2. 服务器返回时的随机数 3. 客户端收到返回时的随机数)) TCP三次握手时的第一次的seq序号是怎样产生的 第一次的序号是随机序号,但也不是完全随机,它是使用一个ISN算法得到的。 seq = C + H (源IP地址,目的IP地址,源端口,目的端口)。其中,C是一个计时器,每隔一段时间值就会变大,H是消息摘要算法,输入是一个四元组(源IP地址,目的IP地址,源端口,目的端口)。
SSL是传输层的协议 https包括非对称加密和对称加密两个阶段,在客户端与服务器建立连接的时候使用非对称加密,连接建立以后使用的是对称加密
** 一个机器能够使用的端口号上限是多少,为什么?可以改变吗?那如果想要用的端口超过这个限制怎么办?** 65536.因为TCP的报文头部中源端口号和目的端口号的长度是16位,也就是可以表示2^16=65536个不同端口号,因此TCP可供识别的端口号最多只有65536个。但是由于0到1023是知名服务端口,所以实际上还要少1024个端口号。 而对于服务器来说,可以开的端口号与65536无关,其实是受限于Linux可以打开的文件数量,并且可以通过MaxUserPort来进行配置。 对称密码和非对称密码体系:
对称加密: 加密和解密的秘钥使用的是同一个 DES,3DES,IDEA,CR4,CR5,CR6,AES **非对称加密:**与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥 RSA,ECC,DSA
数字证书的了解
权威CA使用私钥将网站A的信息和消息摘要(签名S)进行加密打包形成数字证书。公钥给客户端。 网站A将自己的信息和数字证书发给客户端,客户端用CA的公钥对数字证书进行解密,得到签名S,与手动将网站的信息进行消息摘要得到的结果S*进行对比,如果签名一致就证明网站A可以信任。
**非对称加密算法实现及密信息交换过程:甲方生成一对密钥并将其中的一把作为公用密钥向其它方公开;得到该公用密钥的乙方使用该密钥对机密信息进行加密后再发送给甲方;甲方再用自己保存的另一把专用密钥对加密后的信息进行解密。甲方只能用其专用密钥解密由其公用密钥加密后的任何信息。 ** 服务器出现大量close_wait的连接的原因以及解决方法
close_wait状态是在TCP四次挥手的时候收到FIN但是没有发送自己的FIN时出现的,服务器出现大量close_wait状态的原因有两种: 原因1:服务器内部业务处理占用了过多时间,都没能处理完业务;或者还有数据需要发送;或者服务器的业务逻辑有问题,没有执行close()方法 **原因2:**服务器的父进程派生出子进程,子进程继承了socket,收到FIN的时候子进程处理但父进程没有处理该信号,导致socket的引用不为0无法回收 解决 1.停止应用程序 2.修改程序里的bug TCP/IP的粘包与避免介绍一下 因为TCP为了减少额外开销,采取的是流式传输,所以接收端在一次接收的时候有可能一次接收多个包。而TCP粘包就是发送方的若干个数据包到达接收方的时候粘成了一个包。多个包首尾相接,无法区分 原因: 1.发送端等待缓冲区满才进行发送,造成粘包 2.接收方来不及接收缓冲区内的数据,造成粘包 3.由于TCP协议在发送较小的数据包的时候,会将几个包合成一个包后发送 措施: 1.通过编程,强制使TCP发生数据传送,不必等到缓冲区满 2. 优化接收方接收数据的过程,使其来得及接收数据包,包括提高接收进程优先级等 设置固定长度的报文或者设置报文头部指示报文的长度。 说一下TCP的封包和拆包 **封包:**封包就是在发送数据报的时候为每个TCP数据包加上一个包头,将数据报分为包头和包体两个部分。包头是一个固定长度的结构体,里面包含该数据包的总长度 **拆包:接收方在接收到报文后提取包头中的长度信息进行截取 ** 一个ip配置多个域名,靠什么识别 靠host主机名区分 靠端口号区分 DNS的工作过程和原理
**DNS解析有两种方式:递归查询和迭代查询 ** 递归查询 本地域名服务器->根域名服务器->顶级域名服务器->权限域名服务器 **迭代查询 ** 每一个没有查到会返回上一个的地址 然后都是从本地域名器去查找
OSA七层协议和五层协议,分别有哪些
介绍一下ping的过程,分别用到了哪些协议
ping是使用ICMP协议来进行工作的。 ICMP:网络控制报文协议 1.,ping命令会构建一个ICMP请求数据包,然后由ICMP协议将这个数据包连同目的IP地址源IP地址一起交给IP协议。 2.然后IP协议就会构建一个IP数据报,并且在映射表中查找目的IP对应的mac地址,将其交给数据链路层。 3.然后数据链路层就会构建一个数据帧,附上源mac地址和目的mac地址发送出去。 4.目的主机接收到数据帧后,就会检查包上的mac地址与本机mac是否相符,如果相符,就接收并把其中的信息提取出来交给IP协议,IP协议就会将其中的信息提取出来交给ICMP协议。然后构建一个ICMP应答包,用相同的过程发送回去。
IP寻址和MAC寻址有什么不同,怎么实现的 通过MAC地址寻找主机是MAC地址寻址,通过IP地址寻找主机叫IP地址寻址。它们适用于不同的协议层,IP寻址是网络层,Mac寻址是数据链路层。 IP寻址的过程(ARP协议):主机A想通过IP地址寻找到目标主机,首先分析IP地址确定目标主机与自己是否为同一网段。如果是则查看ARP缓存,或者使用ARP协议发送广播。如果不是,则寻找网关发送ARP数据包 ** UDP如何实现可靠传输** 前提:TCP是强制的可靠性传输,其在IP协议的基础上,发送端对所有的数据进行定时重传,接受端对所有的数据进行排序,,TCP在最左侧的这条线上,可靠性最高,但传输代价也很大,效率上不及UDP。UDP则在最右侧,只有传输效率,不保证可靠,传输代价也较低,择一个折中的方案,那就是UDP可靠传输,即RUDP登场的时刻了。 1.为了保证可靠性,我们需要在发送数据的时候添加重传定时器,重传的定时器可以定时回调发送重传的数据,也支持将接收到ACK的数据从定时器中取出。 2.设置超时时间,由于参照tcp策略,当发生数据重传时接收到ACK,无法判断这个ACK是对初次发送数据的确认还是对重传数据的确认。所以使用第二种rtt计算策略,可以将发送时间记录在数据头中发送出去,接受端在发送确认ACK时,将这个时间戳抄下来顺着ACK返回,这样发送端接收到ACK确认时,就能准确的知道要确认数据的发送时间,由此来计算rtt时间。 3.为了提高网络链路利用率,接收端不能每次接收到数据时都立即发送ACK确认,参考TCP的实现策略。一种是延时ACK,即接收端接收到消息时定制一个pending time,当超时时将这段时间内所有要发送的ACK组合在一起发送,还有一种是捎带ACK,即pending time未到,但恰好也有数据要发送给对端,那么就将ACK捎带在这个数据包中一起发送出去。 发送端 4. 发送窗体来控制发送数据的个数,****TCP将所有的数据平铺在一个buffer里,然后通过移动滑动窗体来控制发送数据流动,RUDP将所有的数据包都放到一个权限队列中,按照发送两个高一级权限数据包一个低一级数据包的规则来调整发送顺序,发送窗体中只有inflight的数据包,当可以发送下一个数据包时,再从权限队列中获取。发送窗体负责对发送后的数据缓存,确认,权限队列负责给发送的数据按优先级排序。 接收端 1.如果是想得到TCP的效果,数据即有序,又可靠,那我们需要给所有到达的数据包发送ACK确认且排队,只有前一个数据包排好队,无乱序时,才能将数据反回给上层 2.如果只实现可靠性,不需要有序,那可以接收到一个数据包时,直接反回给上层,但是要发送ACK确认。 3.如果只需要有序性,不需要可靠性,那可以记录目前收到最大的数据包序号,比这个序号大的数据包返回给上层,比这个序号小的直接丢弃,也不需要发送ACK,因为发送端也不会重传数据 5.传输的建立和连接。 因为我们的协议实现在应用层,没有进程启动的时候也无法发送RST给对端,连接断开时基本参考了TCP的四次挥手实现,继续保留了TIME_WAIT状态来保证网络中上一个连接的数据包不会发送到现任连接上。 6.大体机制终于讲完,其他还有一些数据包序列号标识,随机首个序列号,flow queue,pacing实现等细节在socket上有一个Filters process,这是一个过滤器责任链,所有收发的数据都要通过这个过滤器责任链,其可以对传输的包体进行压缩,加密等处理,我在这里实现了snappy对传输数据的压缩过滤器,额外线程通知过滤器,和大数据包的拆分过滤器。通过双向链表管理所有的过滤器模块,可以很方便的嵌入额外的过滤器过程,在这里也可以实现一些熔断转发之类服务治理相关的过滤器。 总结:
数据包即要携带时间戳,又要携带确认ACK,我们需要给上层发下来的数据添加一个自己的协议头以使双端来识别必要的消息,这里我们可以通过不同的控制标识组合来实现一个变长的协议头,有效利用数据包的传输数据量。
对于一个传输连接而言,我们有了重传机制,确认机制,协议头封装,传输接收控制,但是网络是公共交通,我们如何遵守交通规则,不引起网络阻塞的同时有效利用网络带宽呢
拥塞控制法:BBR TCP的CUBIC: 常规的CUBIC算法通过检测丢包来判断网络拥塞,然后通过控制发送窗体的大小来控制传输在网络中的数据量 分三种情况 1.网络中的数据包极少,此时由于应用发送的数据量小,链路中的路由器数据队列为空,每个数据都能快速发送,并且得到确认 2.应用层发送数据量增大,链路中的数据开始增多,路由器的数据包队列已经开始有排队的情况出现,但是还没有发生丢包,这对发送端来看,表现为RTT时间变长。 3.发送的数据量继续增大,链路中路由器队列已经出现排队排满,这时开始有丢包的情况出现。 缺点: 1.CUBIC算法在第3阶段检测到丢包,开始减小发送窗体的大小,以收缩网络中传输的数据量,在没有发生丢包之前,链路中已经被数据包压的苦不堪言,发送数据的RTT时间已经非常慢 2.CUBIC算法还有一个问题是其控制的输出变量只有发送窗体的大小,当发送窗体增大,应用层有数据到来时,会一股脑的将可发送的数据量全部发送出去
TCP和UDP的区别
1.TCP是面向连接的协议,提供的是可靠传输,在收发数据前需要通过三次握手建立连接,使用ACK对收发的数据进行正确性检验。而UDP是无连接的协议,不管对方有没有收到或者收到的数据是否正确。 2.TCP提供流量控制和拥塞控制,而UDP没有(滑动窗口,只要新包的seq与没有得到确认的最小seq之差小于滑动窗口大小,就可以继续发) 3.TCP对系统资源的要求高于UDP,所以速度也比UDP慢 4.TCP数据包是没有边界的,会出现粘包的问题,UDP包是独立的,不会出现粘包问题 **应用:**所以在应用方面,如果强调数据的完整性和正确性用TCP,当要求性能和速度的时候,使用UDP更加合适。
注意:单凭TCP是不能保证完整性的,要是有伪造TCP包,是无法识别的*
TCP和UDP相关的协议与端口号 https://blog.csdn.net/qq_22080999/article/details/81105051
DNS在进行区域传输的时候使用TCP协议,其它时候则使用UDP协议;
DNS的规范规定了2种类型的DNS服务器,一个叫DNS服务器,一个叫辅助DNS服务器。在一个区中主DNS服务器从自己本机的数据文件中读取该区的DNS数据信息,而辅助DNS服务器则从区的主DNS服务器中读取该区的DNS数据信息。当一个辅助DNS服务器启动时,它需要与主DNS服务器通信,并加载数据信息,这就叫做区传送(zone transfer)。
为什么既使用TCP又使用UDP? 使用tcp
UDP报文的最大长度为512字节,而TCP则允许报文长度超过512字节 1.区域传送时使用TCP:辅域名服务器会定时(一般时3小时)向主域名服务器进行查询以便了解数据是否有变动。如有变动,则会执行一次区域传送,进行数据同步。区域传送将使用TCP而不是UDP,因为数据同步传送的数据量比一个请求和应答的数据量要多得多。 2.TCP是一种可靠的连接,保证了数据的准确性。 使用UDP 客户端向DNS服务器查询域名,一般返回的内容都不超过512字节,用UDP传输即可。不用经过TCP三次握手,这样DNS服务器负载更低,响应更快。虽然从理论上说,客户端也可以指定向DNS服务器查询的时候使用TCP,但事实上,很多DNS服务器进行配置的时候,仅支持UDP查询包。
** TCP(UDP,IP)等首部的认识(http请求报文构成)** TCP的头部大致包括:源端口,目的端口,序号,确认号,偏移位,标志位,校验和等等 **UDP的头部则包括:**源端口,目的端口,长度,校验和。 IP数据包的头部包括:源IP地址,目的IP地址,协议,校验和,总长度等等 https://blog.csdn.net/zhangliangzi/article/details/52554439
网页解析的过程与实现方法 1.首先是html文档解析,浏览器会将html文档生成解析树,也就是DOM树,它由dom元素以及属性节点组成。 2.然后浏览器加载过程中如果遇到了外部css文件或者图片资源,还会另外发送请求来获取css文件和资源,这个请求通常是异步的,不会影响html文档的加载。 3.不过如果浏览器在加载时遇到了js文件,则会挂起渲染的线程,等待js文件加载解析完毕才恢复html的渲染线程。 4.然后是css解析,将css文件解析为样式表对象来渲染DOM树。
在浏览器中输入URL后执行的全部过程(如www.baidu.com)重点、热门问题 1.首先是域名解析,客户端使用DNS协议将URL解析为对应的IP地址; 2.然后建立TCP连接,客户端与服务器通过三次握手建立TCP连接 3.接着是http连接,客户端向服务器发送http连接请求; (http连接无需额外连接,直接通过已经建立的TCP连接发送) 4.服务器对客户端发来的http请求进行处理,并返回响应 5.客户端接收到http响应,将结果渲染展示给用户。
网络层分片的原因与具体实现(TCP/IP协议中分包与重组原理介绍 ) **IP分片:**IP分片是网络上传输IP报文的一种技术手段。IP协议在传输数据包时,将数据报文分为若干分片进行传输,并在目标系统中进行重组。这一过程称为分片
为什么要进行IP分片: 每一种物理网络都会规定链路层数据帧的最大长度,称为链路层MTU,IP协议在传输数据包时,若IP数据报加上数据帧头部后长度大于MTU,则将数据报文分为若干分片进行传输,并在目标系统中进行重组. IP分片原理及分析 分片和重新组装的过程对传输层是透明的,其原因是当IP数据报进行分片之后,只有当它到达目的站时,才可进行重新组装,且它是由目的端的IP层来完成的。分片之后的数据报根据需要也可以再次进行分片。 IP分片和完整IP报文差不多拥有相同的IP头,16位ID域对于每个分片都是一致的,这样才能在重新组装的时候识别出来自同一个IP报文的分片。在IP头里面,16位识别号唯一记录了一个IP包的ID,具有同一个ID的IP分片将会重新组装;而13位片偏移则记录了某IP片相对整个包的位置;而这两个表中间的3位标志则标志着该分片后面是否还有新的分片。这三个标志就组成了IP分片的所有信息(将在后面介绍),接受方就可以利用这些信息对IP数据进行重新组织。 标志字段的作用 R:保留未用;DF:Don’t Fragment,“不分片”位,如果将这一比特置1,IP 层将不对数据报进行分片;MF:More Fragment,“更多的片”,除了最后一片外,其它每个组成数据报的片都要把比特置1;Fragment Offset:该片偏移原始数据包开始处的位置。偏移的字节数是该值乘以8。
MTU原理 分片最大的坏处就是降低了传输性能,本来一次可以搞定的事情,分成多次搞定,所以在网络层更高一层(就是传输层) 的实现中往往会对此加以注意!有些高层因为某些原因就会要求我这个面包不能切片,我要完整地面包,所以会在IP数据包包头里面加上一个标签:DF(Don‘t Fragment)。这样当这个IP数据包在一大段网络(水管里面)传输的时候,如果遇到MTU小于IP数据包的情况,转发设备就会根据要求丢弃这个数据包。然后返回一个错误信息给发送者。这样
对于UDP协议而言,这个协议本身是无连接的协议,对数据包的到达顺序以及是否正确到达并不关心,所以一般UDP应用对分片没有特殊要求。 对于TCP协议而言就不一样了,这个协议是面向连接的协议,对于TCP协议而言它非常在意数据包的到达顺序以及是否传输中有错误发生。所以有些TCP应用对分片有要求---不能分片(DF)。 MSS原理 MSS(Maxmum Sigmentation Size)就是TCP数据包每次能够传输的最大数据分段,为了达到最佳的传输效能TCP协议在建立连接的时候通常要协商双方的MSS值,这个值TCP协议在实现的时候往往用MTU值代替(需要减去IP数据包包头的大小20字节和TCP数据段的包头20字节)所以往往MSS为1460。通讯双方会根据双方提供的MSS值的最小值确定为这次连接的最大MSS值。
为什么避免IP分片 尽管IP分片过程看起来是透明的,但有一点让人不想使用它:即使只丢失一片数据也要重传整个数据报。因为IP层本身没有超时重传的机制——由更高层来负责超时和重传(TCP有超时和重传机制,但UDP没有。一些UDP应用程序本身也执行超时和重传)。当来自TCP报文段的某一片丢失后,TCP在超时后会重发整个TCP报文段,该报文段对应于一份IP数据报。没有办法只重传数据报中的一个数据报片。事实上,如果对数据报分片的是中间路由器,而不是起始端系统,那么起始端系统就无法知道数据报是如何被分片的。就这个原因,经常需要避免分片。 IP分片算法的原理 分片重组是IP层一个最重要的工作,其处理的主要思想:当数据包从一个网络A进入另一个网络B时,若原网络的数据包大于另一个网络或者接口的MTU长度,则需要进行分片(若设置DF为1,则丢弃,并回送ICMP不可达差错报文)。因而在IP数据包的报头有若干标识域注明分片包的共同标识号、分片的偏移量、是否最后一片及是否允许分片。传输途中的网关利用这些标识域进可能的再行分片,目有主机把收到的分片进行重组以恢重数据。因此**,分片包在经过网络监测设备、安全设备、系统管理设备时,为了获取信息、处理数据,都必须完成数据包的分片或重组。**