TCP全解

网络模型

TCP/IP协议族

TCP协议简介

TCP是一个面向连接的传输层协议,虽然TCP不属于ISO制定的协议集,但由于其在商业界和工业界的成功应用,它已成为事实上的网络标准,广泛应用于各种网络主机间的通信。

作为一个面向连接的传输层协议,TCP的目标是为用户提供可靠的端到端连接,保证信息有序无误的传输。它除了提供基本的数据传输功能外,还为保证可靠性采用了数据编号、校验和计算、数据确认等一系列措施。它对传送的每个数据字节都进行编号,并请求接收方回传确认信息(ACK)。发送方如果在规定的时间内没有收到数据确认,就重传该数据。

(1)数据编号使接收方能够处理数据的失序和重复问题。

(2)数据误码问题通过在每个传输的数据段中增加校验和予以解决,接收方在接收到数据后检查校验和,若校验和有误,则丢弃该有误码的数据段,并要求发送方重传。

(3)流量控制也是保证可靠性的一个重要措施,若无流控,可能会因接收缓冲区溢出而丢失大量数据,导致许多重传,造成网络拥塞恶性循环。

(4)TCP采用可变窗口进行流量控制,由接收方控制发送方发送的数据量。

TCP为用户提供了高可靠性的网络传输服务,但可靠性保障措施也影响了传输效率。因此,在实际工程应用中,只有关键数据的传输才采用TCP,而普通数据的传输一般采用高效率的UDP。

TCP与UDP的头部

TCP

UDP

TCP的长连接和短连接。

(1)长连接

Client方与Server方先建立通讯连接,连接建立后 不断开, 然后再进行报文发送和接收。

(2)短连接

Client方与Server每进行一次报文收发交易时才进行通讯连接,交易完毕后立即断开连接。此种方式常用于一点对多点通讯,比如多个Client连接一个Server.

使用TCP协议连续传输大量数据时,是否会丢包,应如何避免

这个问题看看似比较容易,但很多人有不同的理解。开发中遇到是否每包(包数据可能大于1460)发送完之后需要由server->client确认一下,还是等待发送完成之后再确认。个人一直坚持用后者,开发中测试发现,client发送出来的数据到server->client确认,这个有时好几秒甚至更长时间.在此记录以便今后参考.

比如发送文件。记得有人提过可能会发生什么堆栈溢出。怎样避免呢?是不是可以收到数据后发送确认包,收到确认包后再继续发送。或是发送方发送了一些数据后sleep一下。
还有,我们都知道,使用UDP协议发送包时需要确认,但TCP协议时面向连接的可靠传输,是不是发出的包肯定可以收到,不需要确认呢?
比如发送文件。记得有人提过可能会发生什么堆栈溢出。怎样避免呢?
------->分段发送,定长接收,正确接收后响应前台
例如:
前台-->后台:先发文件名,长度等信息,
后台-->前台:发OK0(这个0表示期待接收的文件偏移)
。。
前台-->后台:发一段
后台-->前台:发OK,下一段偏移。
。。
重复。。到发完
使用UDP协议发送包时需要确认,但TCP协议时面向连接的可靠传输,是不是发出的包肯定可以收到,不需要确认呢?
--->不一定,虽然TCP保证你的数据传输,但是万一接收方突然拆线,或者中间交换设备掉线,那么数据完全可能到不到后台,因此得发接收响应包确认。
丢包是因为发送端发送太快时,接收端会把后面的包和前面的包叠起来了,例如
发送端:发送包1,发送包2
接收端只收到一个包,内容是:1+2
我以前也遇到个这种情况,后来用下面的方法解决了替每个包加一个包头(数据长度+数据,不用担心粘包问题,但需要解析),接收缓冲区建足够大,然后把接收缓冲区里解出来的包放到一个消息队列里
PS:最好发送时就在包头里标下整个包的长度,方便解包
队列可以用STL中的deque容器解决
如果TCP的发送函数返回成功 那么就是一定发送成功了,这是TCP协议的特征掉线后发送函数肯定会返回错误

比如发送文件。记得有人提过可能会发生什么堆栈溢出。???
TCP
传输是可以保证数据交换的可靠性的,但这是指一方的主机将数据正确的传输到目标机器中,目标机器的协议栈的堆栈是有一定限制的,如果在目标机器中不及时处理接收到的数据,有可能堆栈会溢出!而这种溢出并不是因为TCP协议本身,而是因为系统的IP协议栈的缓冲区溢出造成!
应该说来是可以避免的,在发送端需要加入Select()选项,等待Select()返回后才会发送下一个包。
Select()作用判断当前网络是否可读或者可写,如果不可读或者不可写函数会被阻塞。
虽然这样可能会影响一些速度,但是一般不会造成堆栈溢出的。

youngwhz(sunbird) 说得非常对。
建议的解决方法:
将文件分块发送,接收端每收到一块数据就发送一个收到确认给发送方(包括收到的数据长度)
发送方在收到接收方发送的收到确认后才接着发送下一块数据。。。。
直到整个文件发送完毕。
每块数据都加一个包头,里面可以包含一些标志信息,如:是否所有数据发送完毕(即最后一个包了)
Top
TCP
连接在不断开的情况下可以保证不丢数据
系统的IP协议栈的缓冲区溢出不叫溢出,只能说是丢弃包,属于正常现象,只是会影响性能,而且TCP自己就有流控,你做TCP时可以不用考虑
至于收到确认完全不必要,为了对付连接断开,可以每个包都带序号,断开连接时,发送端重发未发送完的包
我觉得很多人没有理解tcp/ip的分层概念
tcp协议时,用send函数发送数据成功,应该指的是应用层向本机tcp那一层传递数据成功,而并非指这些数据已经得到对方tcp层确认.
如果连接正常,你向本机tcp层传递的数据,对方tcp层绝对可以正确收到,这是tcp协议可以保证的,否则tcp的可靠就没有意义了.但是如果网络突然中断了,那么尚还在本机tcp协议栈中未发完的数据将可能被丢弃,因此如果连接中断后你又重新连接发送数据时,你发送数据的依据不能由你传给本机tcp层多少数据来决定,而是应该询问对方应用层已经收到了多少数据
如果你的程序要求发送的数据必须一字不漏的被接受方收到,那么你必须把发送的数据存为文件,然后发送,发送的规则如上所述,另外,文件传完时也应该确认,但是你没必要每个包都确认。
如果没有这个必要,那么你就用不着确认
同意楼上的了.的确,tcpip会帮你确认你的包信息,但是如果由于网络异常引起的,有些时候tcpip也不能够帮你解决,所以建议把东西保存为一个文件,然后分块发送,然后自己添加头尾信息,
不过一般情况下没有这个必要了.
使用TCP协议在任何时候都不会丢包,因为:
TCP/IP模型中,IP层负责发送包但不保证正确接收,而TCP层在IP层上,保证每个包正确接收。
在应用程序中,如果用Socketsend发送一段数据,只要函数返回OK,对方肯定正确接收了。
使用TCP传送数据不用关心数据是否正确接收(TCP保证做到)更不用自己写应答机制(TCP对每个包都作应答)否则就成udp了。
如果网络故障,socket会有错误报告,tcp连接会断开,但是已发送的数据肯定正确发送了,你所需要的就是试图重新连接,然后把没有发送的数据接着发送出去。
楼上:我不太同意你关于send函数的说法
首先必须明确send函数究竟作了什么,他是负责将数据传递给本地tcp层后返回,还是同时负责将应用层传递的数据得到接受方tcp层确认后才返回
如果是后者你说的无疑是正确的,但是,事实上完全不是这样,这是因为如果这样,那么nagle算法就没用了,因为这个算法就是将多次send函数的传入的小数据拼凑成为一个较大的包,然后再发送。
可见,即使是send函数ok了,对方也不一定可以接受到,因为tcp协议只是在tcp层上尽他的义务,而send函数只不过扮演了一个应用层向tcp层传递数据的角色,除此之外,他和tcp层没有任何关系。
还有一种特殊情况,虽说非常罕见,但是并非不可能发生,那就是:如果接受方tcp层确实接受到数据并向发送方发送了确认信息,但是,在他向应用层传递数据时,应用层程序突然崩溃,那么接受方的应用程序也是无法接受到数据的,而此时,发送方tcp层得到了确认信息认为这些数据已经发送成功了,这是一书里举的极端例子,不信的话你可以看一看这本书吧
总之,不要把send函数和tcp协议混在一起,send函数并不是tcp协议里面的东西,send函数并不能保证任何东西,而这些保证是由tcp来完成的
 再说一句,tcp不会丢包和send返回ok接受方一定收到没有任何关系,前者并不意味着后者
没有任何一个函数,协议可以保证完全不丢包,
只不过TCP要好得多,因为它是具有连接和错误重发的协议。
在极端情况下(通信线路突然中断),那么TCP可以报错,应用程序可以重新建立连接再重传。
但是中间如果有第三方攻击(如窃听者或者线路故障),那么TCP也不能保证你的数据完全到了对方,因此在关键的数据交互场合(如网上交易),必须通过应用层的协议加以控制。
每种语言的send函数都不一样啊
如果是异步调用,不保证正确发送
但是我用的是java.net.Socket
只要不发生IOException,那肯定正确发送出去了
我在tcp/ip上学的,怎么与上楼上,上的有很多不同呀?
如果是blocking模式send应该是得到对方TCP协议确认后才返回而不是仅仅得到本机TCP模块回应就返回,否则send永远都返回成功,可以如下测试一下,建立连接后断开物理线路,操作系统不会立即得知物理链路已断开(如拨号),程序再调用send,如果返回失败说明send是等待确认后才返回,如果返回成功就说明send只需要发到本机TCP就返回。

拥塞控制

产生原因

         对资源的需求 > 可用资源

单纯的增加网络资源无法解决问题

Eg:把节点的存储空间扩大,更换更高速率的链路,提高结点处理机的运算速度,不仅不能解决问题,而且可能使网络性能更坏。

原因:网络拥塞是由很多因素引起的,单纯解决一个会转移到其他地方

扩大结点存储空间-à由于输出链路的容量和处理机的速度没有提高,增加排队等待时间,超时重传,浪费资源。

更换更高速率的链路-à可能会缓解,可能造成各部分不匹配。

作用

拥塞控制就是为了防止过多的数据注入到网络中,这样可以使网络中的路由器或者链路不至于过载。拥塞控制要做的都有一个前提:就是网络能够承受现有的网络负荷。

对比流量控制:拥塞控制是一个全局的过程,涉及到所有的主机、路由器、以及降低网络相关的所有因素。流量控制往往指点对点通信量的控制,是端对端的问题。

拥塞窗口:发送方为一个动态变化的窗口叫做拥塞窗口,拥塞窗口的大小取决于网络的拥塞程度。发送方让自己的发送窗口=拥塞窗口,但是发送窗口不是一直等于拥塞窗口的,在网络情况好的时候,拥塞窗口不断的增加,发送方的窗口自然也随着增加,但是接受方的接受能力有限,在发送方的窗口达到某个大小时就不在发生变化了。

发送方如果知道网络拥塞了呢?发送方发送一些报文段时,如果发送方没有在时间间隔内收到接收方的确认报文段,则就可以人为网络出现了拥塞。

算法

慢启动算法的思路:主机开发发送数据报时,如果立即将大量的数据注入到网络中,可能会出现网络的拥塞。慢启动算法就是在主机刚开始发送数据报的时候先探测一下网络的状况,如果网络状况良好,发送方每发送一次文段都能正确的接受确认报文段。那么就从小到大的增加拥塞窗口的大小,即增加发送窗口的大小。

    Eg:开始发送方先设置cwnd(拥塞窗口)=1,发送第一个报文段M1,接收方接收到M1后,发送方接收到接收方的确认后,把cwnd增加到2,接着发送方发送M2、M3,发送方接收到接收方发送的确认后cwnd增加到4,慢启动算法每经过一个传输轮次(认为发送方都成功接收接收方的确认),拥塞窗口cwnd就加倍。

    

拥塞避免:为了防止cwnd增加过快而导致网络拥塞,所以需要设置一个慢开始门限ssthresh状态变量(我也不知道这个到底是什么,就认为他是一个拥塞控制的标识),它的用法:

     1. 当cwnd < ssthresh,使用慢启动算法,

     2. 当cwnd > ssthresh,使用拥塞控制算法,停用慢启动算法。

     3. 当cwnd = ssthresh,这两个算法都可以。

 

拥塞避免的思路:是让cwnd缓慢的增加而不是加倍的增长,每经历过一次往返时间就使cwnd增加1,而不是加倍,这样使cwnd缓慢的增长,比慢启动要慢的多。

    无论是慢启动算法还是拥塞避免算法,只要判断网络出现拥塞,就要把慢启动开始门限(ssthresh)设置为设置为发送窗口的一半(>=2),cwnd(拥塞窗口)设置为1,然后在使用慢启动算法,这样做的目的能迅速的减少主机向网络中传输数据,使发生拥塞的路由器能够把队列中堆积的分组处理完毕。拥塞窗口是按照线性的规律增长,比慢启动算法拥塞窗口增长块的多。

  Eg:1.TCP连接进行初始化的时候,cwnd=1,ssthresh=16。

     2.在慢启动算法开始时,cwnd的初始值是1,每次发送方收到一个ACK拥塞窗口就增加1,当ssthresh =cwnd时,就启动拥塞控制算法,拥塞窗口按照规律增长,

     3.当cwnd=24时,网络出现超时,发送方收不到确认ACK,此时设置ssthresh=12,(二分之一cwnd),设置cwnd=1,然后开始慢启动算法,当cwnd=ssthresh=12,慢启动算法变为拥塞控制算法,cwnd按照线性的速度进行增长。

AIMD(加法增大乘法减小)

    1. 乘法减小:无论在慢启动阶段还是在拥塞控制阶段,只要网络出现超时,就是将cwnd置为1,ssthresh置为cwnd的一半,然后开始执行慢启动算法(cwnd<ssthresh)。

    2. 加法增大:当网络频发出现超时情况时,ssthresh就下降的很快,为了减少注入到网络中的分组数,而加法增大是指执行拥塞避免算法后,是拥塞窗口缓慢的增大,以防止网络过早出现拥塞。

   这两个结合起来就是AIMD算法,是使用最广泛的算法。拥塞避免算法不能够完全的避免网络拥塞,通过控制拥塞窗口的大小只能使网络不易出现拥塞。

快重传算法要求首先接收方收到一个失序的报文段后就立刻发出重复确认,而不要等待自己发送数据时才进行捎带确认。接收方成功的接受了发送方发送来的M1、M2并且分别给发送了ACK,现在接收方没有收到M3,而接收到了M4,显然接收方不能确认M4,因为M4是失序的报文段。如果根据可靠性传输原理接收方什么都不做,但是按照快速重传算法,在收到M4、M5等报文段的时候,不断重复的向发送方发送M2的ACK,如果接收方一连收到三个重复的ACK,那么发送方不必等待重传计时器到期,由于发送方尽早重传未被确认的报文段。

快恢复:

(1)当发送发连续接收到三个确认时,就执行乘法减小算法,把慢启动开始门限(ssthresh)减半,但是接下来并不执行慢开始算法。

(2)此时不执行慢启动算法,而是把cwnd设置为ssthresh的一半, 然后执行拥塞避免算法,使拥塞窗口缓慢增大。

流量控制

具体的流量控制采用的技术是滑动窗口,以便于通信双方能够充分利用带宽。流量控制作为接收方管理发送方发送数据的方式,用来防止接收方可用的数据缓存空间溢出。滑动窗口允许发送方在收到接收到方的确认之前发送多个数据段,窗口的大小确定了在收到目的地确认之前,一次可以传送的数据段最大数目,窗口越大,主机一次可以传输的数据段就越多。当主机传输窗口大小数目的数据段后,就必须等收到确认,才可以再传输下面的数据段。

窗口的大小在通信双方连接期间是可变的,通信双方可以通过协商动态的修改窗口的大小。在TCP的每一个确认中,除了指出希望收到的下一个数据段的序列号之外,还包括一个窗口通告,通告中指出了接收方还能再收多少数据段(可以把通告看成接收缓冲区的大小)。如果通告值增大,窗口也相应增大;反之亦然。但是可以发现,接收端并没有特别合适的方法来判断当前网络是否拥塞,因为它只是被动接收,不像发送端,当发出一个数据段后,会等待对方的确认信息,如果超时,就可以认为网络拥塞,所以,改变窗口大小的唯一根据,就是接收缓冲区的大小了。

流量控制是一种局部控制机制,参与者仅仅是发送方和接收方,它只考虑了接收端的接收能力,而没有考虑到网络的传输能力。

拥塞控制注重于整体,考虑的是整个网络的传输能力,是一种全局控制机制,正因为流量控制的这种局限性,从而导致了拥塞崩溃现象的发生。

图解流控过程:

流量控制的两个算法:

漏桶算法:限流算法

 

令牌桶算法:处理突发请求量过大

 

优缺点

TCP:

   1.优点:

      可靠、稳定:三次握手、四次挥手、确认、窗口、重传、拥塞控制机制,数据传输完成之后断开连接来节省资源。

   2、缺点:

       慢、效率比较,占用系统资源。容易受攻击:建立连接会消耗时间,确认机制,重传机制和拥塞控制都会消耗大量的时间,而且要在每台设备上维护所有的传输连接。而且每一个连接都会占用系统的CPU,内存硬件等资源。而且三次握手容易被人利用,实现DOS和DDOS攻击。

UDP:

1、优点:

快:UDP是无状态的传输机制,所以在传输数据时非常快,UDP也没有乱七

八糟的机制,相应被利用的漏铜就少一点,但是UDP的攻击也存在,比如UDP的flood攻击。

    2、缺点

      不可靠、不稳定

 

参考:https://blog.csdn.net/changyourmind/article/details/53127100

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Modbus是一种通信协议,它是用于工业控制系统的最普遍的通信协议之一。Modbus TCP则是一种基于TCP/IP协议的Modbus通信方式,它可以在以太网上进行数据传输和通信控制。为了建立TCP连接,应用程序可以使用Socket API,Socket是一种通信机制,它提供了网络上信息传输的抽象概念。 Modbus TCP使用Socket API中的TCP套接字,这是一种面向连接的可靠数据流协议。TCP套接字提供了连接性,有序性,可靠性和流控制等特性,确保了Modbus TCP通信的稳定性和可靠性。在Modbus TCP通信中,通信双方需要事先建立TCP连接,然后在这个连接上使用Modbus消息进行通信。 使用Modbus TCP和Socket API,可以实现远程监控和控制,例如可以远程控制PLC或传感器,读取实时数据。除此之外,还可以通过Modbus TCP和Socket API实现数据记录和报告,以及故障诊断和预测等功能。因此,Modbus TCP和Socket API是现代工业控制系统中必不可少的通信和网络技术。 ### 回答2: Modbus是一种通信协议,而TCP则是一种网络传输协议,二者可以组合使用,形成Modbus TCP协议,以实现通过网络连接的设备间的数据通信。 Socket通常指网络资源的标识符,它含了访问网络资源所需的信息和参数,如IP地址、端口号等。TCP Socket则是用于TCP连接的一种Socket类型,它实现了TCP协议中的连接、数据传输和关闭等功能。 在Modbus TCP协议中,数据是通过TCP Socket传输的。设备通过TCP Socket连接到网络,然后通过Modbus TCP消息格式进行通信,可以完成数据的读、写、读写等操作。TCP Socket作为Modbus TCP协议的支持,实现了设备之间的高效、可靠的数据传输。 总之,Modbus TCP和Socket TCP是两种不同的协议,但它们之间可以组合使用,构成高效、可靠的网络数据通信和控制系统。 ### 回答3: Modbus TCP和Socket TCP是两种不同的通讯协议,它们之间没有直接的联系也不是互相替代的关系。 Modbus TCP是基于TCP/IP协议的Modbus协议的一种实现方式,Modbus是一种常见的工业控制设备间通讯协议,括串行、以太网和其他网络通讯方式。而Modbus TCP则是采用TCP/IP协议在以太网上实现的基于Modbus协议的通讯方式,具有广泛的应用场景,例如自动化和工程控制、制造业自动化等领域。 Socket TCP是一种常用的网络通讯协议,它是一种全双工、面向连接、基于字节流的网络协议,用于实现网络间的数据传输。Socket TCP支持客户端和服务器的通讯,客户端可以向服务器发起连接请求并发送数据,而服务器则接受连接请求并处理客户端发来的数据。Socket TCP也是一种广泛应用于通讯领域的协议,例如基于TCP/IP协议的Web应用、实时控制器、通讯服务器等。 总之,Modbus TCP和Socket TCP是两种不同的通讯协议,它们都有各自的应用场景和优势。使用时需要根据具体情况进行选择,或者结合两种协议进行联合应用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值