- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
计算机网络基础,考验一个程序员的基本功,也能更快的筛选出更优秀的人才.
假设发送端为客户端,接收端为服务端。开始时客户端和服务端的状态都是 CLOSED .
SYN=1
,序列号 seq=x
。第一次握手前客户端的状态为 CLOSE
,第一次握手后客户端的状态为 SYN-SENT
。此时服务端的状态为 LISTEN
。 SYN=1
, ACK=1
,序列号 seq=y
,确认号 ack=x+1
。第二次握手前服务端的状态为 LISTEN
,第二次握手后服务端的状态为 SYN-RCVD
,此时客户端的状态为 SYN-SENT
。(其中 SYN=1
表示要和客户端建立一个连接, ACK=1
表示确认序号有效) ACK=1
,序列号 seq=x+1
,确认号 ack=y+1
。第三次握手前客户端的状态为 SYN-SENT
,第三次握手后客户端和服务端的状态都为 ESTABLISHED
。 此时连接建立完成。 之所以需要第三次握手,主要为了 防止已失效的连接请求报文段 突然又传输到了服务端,导致产生问题.
本文已经收录到Github仓库,该仓库包含 计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享 等核心知识点,欢迎star~ 。
Github地址 。
如果访问不了Github,可以访问gitee地址.
gitee地址 。
IP 层是「不可靠」的,它不保证网络包的交付、不保证网络包的按序交付、也不保证网络包中的数据的完整性.
因为 TCP 是一个工作在传输层的可靠数据传输的服务,它能确保接收端接收的网络包是无损坏、无间隔、非冗余和按序的.
FIN=1,seq=u
),并停止再发送数据,主动关闭TCP连接,进入 FIN-WAIT-1
(终止等待1)状态,等待B的确认。 ACK=1,ack=u+1,seq=v
),B进入 CLOSE-WAIT
(关闭等待)状态,此时的TCP处于半关闭状态,A到B的连接释放。 FIN-WAIT-2
(终止等待2)状态,等待B发出的连接释放报文段。 FIN=1,ACK=1,seq=w,ack=u+1
),B进入 LAST-ACK
(最后确认)状态,等待A的确认。 ACK=1,seq=u+1,ack=w+1
),A进入 TIME-WAIT
(时间等待)状态。此时TCP未释放掉,需要经过时间等待计时器设置的时间 2MSL
(最大报文段生存时间)后,A才进入 CLOSED
状态。B收到A发出的确认报文段后关闭连接,若没收到A发出的确认报文段,B就会重传连接释放报文段。 ACK
报文段有可能丢失,B收不到这个确认报文,就会超时重传连接释放报文段,然后A可以在 2MSL
时间内收到这个重传的连接释放报文段,接着A重传一次确认,重新启动2MSL计时器,最后A和B都进入到 CLOSED
状态,若A在 TIME-WAIT
状态不等待一段时间,而是发送完ACK报文段后立即释放连接,则无法收到B重传的连接释放报文段,所以不会再发送一次确认报文段,B就无法正常进入到 CLOSED
状态。 ACK
报文段后,再经过2MSL,就可以使这个连接所产生的所有报文段都从网络中消失,使下一个新的连接中不会出现旧的连接请求报文段。 因为当Server端收到Client端的 SYN 连接请求报文后,可以直接发送 SYN+ACK 报文。 但是在关闭连接时,当Server端收到Client端发出的连接释放报文时,很可能并不会立即关闭SOCKET ,所以Server端先回复一个 ACK 报文,告诉Client端我收到你的连接释放报文了。只有等到Server端所有的报文都发送完了,这时Server端才能发送连接释放报文,之后两边才会真正的断开连接。故需要四次挥手.
最全面的Java面试网站 。
基于TCP的应用层协议有:HTTP、FTP、SMTP、TELNET、SSH 。
基于UDP的应用层协议:DNS、TFTP、SNMP 。
TCP是面向流,没有界限的一串数据。TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一 个完整的包可能会被TCP拆分成多个包进行发送 , 也有可能把多个小的包封装成一个大的数据包发送 ,这就是所谓的TCP粘包和拆包问题.
为什么会产生粘包和拆包呢?
解决方案:
TCP 利用滑动窗口实现流量控制。流量控制是为了控制发送方发送速率,保证接收方来得及接收。 TCP会话的双方都各自维护一个发送窗口和一个接收窗口。接收窗口大小取决于应用、系统、硬件的限制。发送窗口则取决于对端通告的接收窗口。接收方发送的确认报文中的window字段可以用来控制发送方窗口大小,从而影响发送方的发送速率。将接收方的确认报文window字段设置为 0,则发送方不能发送数据.
TCP头包含window字段,16bit位,它代表的是窗口的字节容量,最大为65535。这个字段是接收端告诉发送端自己还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。接收窗口的大小是约等于发送窗口的大小.
防止过多的数据注入到网络中。 几种拥塞控制方法:慢开始( slow-start )、拥塞避免( congestion avoidance )、快重传( fast retransmit )和快恢复( fast recovery ).
慢开始 。
把拥塞窗口 cwnd 设置为一个最大报文段MSS的数值。而在每收到一个对新的报文段的确认后,把拥塞窗口增加至多一个MSS的数值。每经过一个传输轮次,拥塞窗口 cwnd 就加倍。 为了防止拥塞窗口cwnd增长过大引起网络拥塞,还需要设置一个慢开始门限ssthresh状态变量.
当 cwnd < ssthresh 时,使用慢开始算法.
当 cwnd > ssthresh 时,停止使用慢开始算法而改用拥塞避免算法.
当 cwnd = ssthresh 时,既可使用慢开始算法,也可使用拥塞控制避免算法.
拥塞避免 。
让拥塞窗口cwnd缓慢地增大,每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1,而不是加倍。这样拥塞窗口cwnd按线性规律缓慢增长.
无论在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞(其根据就是没有收到确认),就要把慢开始门限ssthresh设置为出现拥塞时的发送 方窗口值的一半(但不能小于2)。然后把拥塞窗口cwnd重新设置为1,执行慢开始算法。这样做的目的就是要迅速减少主机发送到网络中的分组数,使得发生 拥塞的路由器有足够时间把队列中积压的分组处理完毕.
最全面的Java面试网站 。
快重传 。
有时个别报文段会在网络中丢失,但实际上网络并未发生拥塞。如果发送方迟迟收不到确认,就会产生超时,就会误认为网络发生了拥塞。这就导致发送方错误地启动慢开始,把拥塞窗口cwnd又设置为1,因而降低了传输效率.
快重传算法可以避免这个问题。快重传算法首先要求接收方每收到一个失序的报文段后就立即发出重复确认,使发送方及早知道有报文段没有到达对方.
发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待重传计时器到期。由于发送方尽早重传未被确认的报文段,因此采用快重传后可以使整个网络吞吐量提高约20%.
快恢复 。
当发送方连续收到三个重复确认,就会把慢开始门限ssthresh减半,接着把cwnd值设置为慢开始门限ssthresh减半后的数值,然后开始执行拥塞避免算法,使拥塞窗口缓慢地线性增大.
在采用快恢复算法时,慢开始算法只是在TCP连接建立时和网络出现超时时才使用。 采用这样的拥塞控制方法使得TCP的性能有明显的改进.
我们都知道 TCP 连接建立是需要三次握手,假设攻击者短时间伪造不同 IP 地址的 SYN 报文,服务端每接收到 一个 SYN 报文,就进入 SYN_RCVD 状态,但服务端发送出去的 ACK + SYN 报文,无法得到未知 IP 主机的ACK 应答,久而久之就会占满服务端的 SYN 接收队列(未连接队列),使得服务器不能为正常用户服务.
TCP 四元组可以唯一的确定一个连接,四元组包括如下: 源地址 源端口 目的地址 目的端口.
源地址和目的地址的字段(32位)是在 IP 头部中,作用是通过 IP 协议发送报文给对方主机.
源端口和目的端口的字段(16位)是在 TCP 头部中,作用是告诉 TCP 协议应该把报文发给哪个进程.
最后给大家分享一个Github仓库,上面有大彬整理的 300多本经典的计算机书籍PDF ,包括 C语言、C++、Java、Python、前端、数据库、操作系统、计算机网络、数据结构和算法、机器学习、编程人生 等,可以star一下,下次找书直接在上面搜索,仓库持续更新中~ 。
Github地址 : https://github.com/Tyson0314/java-books 。
最后此篇关于这可能是最全面的TCP面试八股文了的文章就讲到这里了,如果你想了解更多关于这可能是最全面的TCP面试八股文了的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
这很可能是我的语法错误,因为我对在 C++ 中使用多个文件和结构(特别是将结构传递给函数)还很陌生。这是三个文件: 主要.cpp: #include #include #include #inc
我有 TypeScript NestJS 项目。 我需要验证传入的 DTO 到我的 API。它可以被描述为“创建项目”,其中我们有建筑类型(房屋、公寓、花园),并根据该类型我们需要定义: 房屋:楼层包
是否可以从可用于泛型参数的可能类型集中排除特定类型?如果是如何。 例如 Foo() : where T != bool 将意味着除了类型 bool 之外的任何类型。 编辑 为什么? 以下代码是我尝试强
我的 WebGL 体积光线转换应用程序即将完成。但是我发现了一个问题。我必须通过 2D 纹理模拟 3D 纹理。这不是问题。我正在用小切片创建一个巨大的纹理。巨大纹理的尺寸约为 4096x4096 像素
我正在处理的网页上显示了一个返回顶部按钮。当您向下滚动时,有时单击它时,它会跳到顶部,然后跳回您在页面上的位置,然后像预期的那样平滑滚动到顶部。请记住,它并不总是这样做。这只是一个滞后或故障问题还是我
我对此还很陌生,所以请耐心等待。 我有一个类,它具有三个属性:几个整数和一个用户定义对象的集合。 public class Response { public int num1 { get;
我正在制作一款平台游戏,让玩家每 30 毫秒跳跃一次,并向上添加少量的力。我想我应该使用多线程,因为我之前已经做过一些,而且看起来很简单。无论如何,我尝试了这个: public void jump()
是否可以从可能的类型集中排除特定类型,这些类型可以在泛型参数中使用?如果是这样的话。 例如 Foo() : where T != bool 表示除 bool 类型之外的任何类型。 编辑 为什么? 以下
我正在尝试在单个查询中实现内部和外部联接,我不确定我的做法是正确还是错误,因为我不太擅长查询。 就这样吧。 我有以下表格。 hrs_residentials hrs_residential_utili
关于 my website ,有一段代码可以向页面添加几个元素。这段代码不是我可以编辑的东西,而且我对它放置这些元素的位置不满意,因为它弄乱了我的一些布局。所以我想出了一个小的 jQuery 来将它们
一位客户希望我创建一个数据集,如下所示。我不知道这是否可能或合乎逻辑。 我有表parent: id name ------- ------- 1 parent1 2
这可能吗?google 好像没有这方面的资料.. 这样,如果用户在另一个网站上播放视频或歌曲,我的音量就会自动减小 最佳答案 不,这是不可能的。 如果可能的话,它必须是特定于浏览器的,但我不认为这种情
所以我正在尝试制作响应式页面。问题是为什么它归结为移动数据需要位于列表中。 我会用一些示例代码来解释 所以这可能是桌面上的输出 option1
当您将鼠标悬停在a 元素 上时,是否可以删除url? 这就是我的意思: 最佳答案 一种选择是使用一些 JavaScript。 删除 href=来自 的属性标签,取而代之的是 onclick=...
我已经考虑了几个小时,但我无法取得太大进展。它是这样的: You have an array of size n and q queries. Each query is of the form (l
我一直在尝试编写一个脚本来强化 android。我没有成功! 我正在通过模拟器运行一个 AVD,并且已经用我加载的 android shell 和 bash shell 试过了。正如您将在下面看到的那
Private Sub Workbook_Open() Dim WBname As String WBname = ThisWorkbook.name If Not InStr(WBname, "te
Spark 2.0.0-预览版 我们有一个应用程序使用了相当大的广播变量。我们在大型 EC2 实例上运行它,因此部署处于客户端模式。广播变量是一个巨大的 Map[String, Array[Strin
我正在尝试从此link中提取摘要。但是,我无法仅提取摘要的内容。到目前为止,这是我完成的工作: url <- "http://www.scielo.br/scielo.php?script=sci_a
我的主页中有一个iframe。 iframe页面中有一个modalpopup。因此,当显示modalpopup时,modalpopup的父级是iframe主体和主页父级主体。因此,覆盖层仅覆盖ifra
我是一名优秀的程序员,十分优秀!