TCP伪代码
- 格式:docx
- 大小:15.77 KB
- 文档页数:2
计算机网络中的拥塞控制算法一、引言计算机网络中的拥塞控制算法是指在网络传输数据时,为了避免网络拥塞导致传输性能下降、数据丢失等问题,采用的一种控制方法。
拥塞控制算法包括多种,如TCP的拥塞控制算法、UDP 的拥塞控制算法、RED算法等,本文将重点介绍TCP的拥塞控制算法。
二、TCP的拥塞控制算法TCP的拥塞控制算法主要包括四种:慢启动、拥塞避免、快速重传、快速恢复。
1. 慢启动慢启动是TCP连接刚开始传送数据时启用的一种算法。
慢启动将初始窗口大小设为一个很小的值,然后每经过一个往返时间RTT,增加窗口的大小,直到达到一个拥塞阈值(cwnd)。
超过拥塞阈值后,进入拥塞避免算法。
慢启动中主要涉及两个参数:拥塞窗口大小(cwnd)和拥塞阈值(ssthresh)。
慢启动的主要思想是控制发送方数据速率,使其不断逼近网络的传输极限。
通过控制拥塞窗口大小,发送方可以平衡网络吞吐量和丢包率,避免网络拥塞。
慢启动算法的伪代码如下:if (cwnd <= ssthresh) {cwnd = cwnd + 1;} else {cwnd = cwnd + 1/cwnd;}2. 拥塞避免拥塞避免算法是在慢启动后,当拥塞窗口大小超过拥塞阈值时启用的一种算法。
拥塞避免算法中,每经过一个RTT,拥塞窗口的大小增加一个MSS(最大分段大小),从而每个RTT可以传输更多的数据。
当出现拥塞情况时,TCP会将拥塞阈值减半,同时进入慢启动算法。
拥塞避免算法的伪代码如下:if (cwnd > ssthresh) {cwnd = cwnd + 1/cwnd;}3. 快速重传快速重传算法是当TCP收到重复的数据时,立即发送重复的确认,而不等待超时重传计时器,从而提高数据传输的速率。
当收到重复的确认后,TCP会将拥塞窗口大小减半并重新进入拥塞避免算法。
快速重传算法的伪代码如下:if (duplicate_ack_received) {cwnd = cwnd/2;ssthresh = cwnd;}4. 快速恢复快速恢复算法是在快速重传算法后,立即发送数据而不等待拥塞避免算法重新检查网络,从而提高数据传输的速率。
本章是part II的最后一章。
第5章介绍如何减少数据包拷贝开销,第6章介绍如何减少控制开销,端节点上最大的性能提升往往来自这两个方面,现代网络实现基本上已经注意了这些问题。
第7章和第8章分别介绍定时器和提前解复用实现的性能瓶颈和解决方法。
由于课时的关系,我们先介绍第9章,这些是较常见的处理任务,然后再介绍第3章、第4章,这两章是对网络算法学15条原则的归纳和运用,是本课程的重点。
如果有时间的话,我们再介绍第7章。
第9章主要介绍缓冲区管理、常规协议处理、分片重组等的实现。
这些协议处理任务看起来不起眼,但是随着链路速度达到吉比特量级,这些任务也不能忽视。
因为在极高的速度下,每个包的处理时间非常短,任何一个环节的低效都可能导致包处理时间超过预定的上限,导致系统整体性能的下降。
另一方面,网络中有许多小包,对于这些小包来说,数据处理并不是主要的开销(数据很少或没有数据,如TCP确认),主要的开销就在一般性的协议处理上(分配包缓冲区,协议头处理等)。
9.1.1 缓冲区分配经典的BSD UNIX实现,称为mbufs。
……Mbufs设计的出发点:(1)用缓冲区链来存放包是为了便于动态扩展包的缓冲空间。
比如,当包从上往下穿过协议栈时,添加一个协议头,就只需要将协议头放到一个mbuf中,然后添加到链表头部。
Mbufs出现的时候是1981年,那时正是各种网络技术全面开花的时期,没有哪一种网络技术占统治地位,将来会出现什么技术也不得而知。
因此,数据包从上往下需要经过哪几层协议处理、每个协议头的长度是多少都无从知道,从而无法知道应当为数据包分配多大的空间。
为了能支持各种可能的协议栈,操作系统必须允许动态扩展包的缓冲空间。
(2)定义不同大小的缓冲区是为了充分利用内存空间。
比如,一个190字节的包会被分配两个mbuf,大约浪费20个字节的空间;一个450字节的包会被分配5个mbuf,浪费大约50个字节。
这在当时(1981年)很重要,因为那时计算机的内存普遍很小。
伪代码伪代码(Pseudocode)是一种算法描述语言。
使用伪代码的目的是为了使被描述的算法可以容易地以任何一种编程语言(Pascal,C,Java,etc)实现。
因此,伪代码必须结构清晰、代码简单、可读性好,并且类似自然语言。
介于自然语言与编程语言之间。
以编程语言的书写形式指明算法职能。
使用伪代码, 不用拘泥于具体实现。
相比程序语言(例如Java, C++,C, Dephi 等等)它更类似自然语言。
它是半角式化、不标准的语言。
可以将整个算法运行过程的结构用接近自然语言的形式(可以使用任何一种你熟悉的文字,关键是把程序的意思表达出来)描述出来。
定义人们在用不同的编程语言实现同一个算法时意识到,他们的实现(注意:这里是实现,不是功能)很不同。
尤其是对于那些熟练于不同编程语言的程序员要理解一个(用其他编程语言编写的程序的)功能时可能很难,因为程序语言的形式限制了程序员对程序关键部分的理解。
这样伪代码就应运而生了。
伪代码提供了更多的设计信息,每一个模块的描述都必须与设计结构图一起出现。
伪代码是一种非正式的,类似于英语结构的,用于描述模块结构图的语言。
应用领域当考虑算法功能(而不是其语言实现)时,伪代码常常得到应用。
伪码中常被用于技术文档和科学出版物中来表示算法,也被用于在软件开发的实际编码过程之前表达程序的逻辑。
伪代码不是用户和分析师的工具,而是设计师和程序员的工具。
计算机科学在教学中通常使用虚拟码,以使得所有的程序员都能理解。
综上,简单的说,让人便于理解的代码。
不依赖于语言的,用来表示程序执行过程,而不一定能编译运行的代码。
在数据结构讲算法的时候用的很多。
伪代码用来表达程序员开始编码前的想法。
语法规则例如,类Pascal语言的伪代码的语法规则是:在伪代码中,每一条指令占一行(else if,例外)。
指令后不跟任何符号(Pascal和C中语句要以分号结尾)。
书写上的“缩进”表示程序中的分支程序结构。
这种缩进风格也适用于if-then-else语句。
tcp伪首部格式-回复相关问题,介绍TCP伪首部格式。
TCP(传输控制协议)是一种可靠的传输层协议,它通过将数据流分割成小的数据段来传输,并在接收端重新组装这些数据段,以确保数据的可靠传输。
TCP伪首部格式是TCP协议数据段的固定头部部分,用于在传输过程中对TCP包进行识别和校验。
TCP伪首部格式是位于TCP头部之前的一段数据,格式如下:源IP地址:占用32位,表示发送端主机的IP地址。
目的IP地址:占用32位,表示接收端主机的IP地址。
保留字段:占用8位,保留未用。
传输层协议标识:占用8位,用于识别传输层的协议,TCP协议为6。
TCP首部长度:占用4位,表示TCP头部的长度。
TCP源端口号:占用16位,表示发送端口号。
TCP目的端口号:占用16位,表示接收端口号。
序号:占用32位,表示数据段的序号。
确认号:占用32位,表示期望接收的下一个数据段的序号。
首部长度:占用4位,表示TCP头部的长度。
标志位:占用6位,用于描述TCP报文的一些属性,如SYN、ACK等。
窗口大小:占用16位,表示接收方可接收数据的窗口大小。
校验和:占用16位,用于检验整个TCP包的完整性。
紧急指针:占用16位,用于标识紧急数据的位置。
从上面的伪首部格式可以看出,TCP伪首部主要包含了源IP地址、目的IP地址、传输层协议标识、TCP首部长度、TCP源端口号、TCP目的端口号、序号、确认号、首部长度、标志位、窗口大小、校验和和紧急指针等字段。
TCP伪首部的作用是为了在传输过程中对TCP包进行识别和校验。
其中,源IP地址和目的IP地址用于标识发送端和接收端的主机。
传输层协议标识为常数6,表示该数据段为TCP协议数据段。
TCP首部长度字段用于指示TCP头部的长度,以便接收方正确解析TCP包。
源端口号和目的端口号用于标识发送端和接收端的端口。
序号和确认号字段用于实现TCP的序列号和确认机制。
标志位字段用于描述TCP报文的一些属性,如SYN用于建立连接,ACK用于确认数据段,FIN用于关闭连接等。
tcp伪首部格式-回复TCP伪首部格式是指在TCP数据报文中,为了确保IP层和传输层的协议之间能够进行正确的匹配和传递数据,TCP引入了伪首部。
伪首部是TCP 数据报文中的一个固定长度为12字节的字段,它并不是TCP头部的一部分,而是位于TCP头部之前。
TCP伪首部包含以下字段:1. 源地址(Source Address):指发送端的IP地址,用于标识数据报文的源地址。
2. 目的地址(Destination Address):指接收端的IP地址,用于标识数据报文的目的地址。
3. 保留字段(Reserved):预留字段,暂时没有使用,都为0。
4. 协议号(Protocol):标识上层的协议类型,TCP的值为6。
5. TCP长度(TCP Length):指TCP头部和数据部分的长度。
当TCP数据报文需要传输时,发送端会首先计算数据部分的长度,然后将上述字段填入伪首部,再连接上TCP头部和数据部分,最后计算TCP首部和数据部分的校验和。
接收端在接收到数据报文后,也会根据伪首部的字段来进行校验和的计算,并与发送端计算得到的校验和进行比对,以确保数据在传输过程中没有发生错误。
伪首部的存在是为了提高TCP的传输可靠性。
它可以防止数据报文在传输过程中被篡改或损坏,并可以帮助接收端进行数据的正确匹配和处理。
通过校验和的比对,接收端可以快速检测到传输中可能出现的错误,并及时给出相应的应对措施,从而确保数据传输的正确性。
需要注意的是,伪首部只在计算校验和的过程中起到作用,传输过程中并不会被传输出去。
伪首部的字段只是作为校验和的输入,而且由于其固定长度和预定义的位置关系,可以确保校验和的计算是唯一而准确的。
总之,TCP伪首部格式在TCP传输中发挥了重要的作用。
通过引入伪首部,TCP可以在传输过程中对数据报文的完整性和正确性进行校验,从而提高了数据传输的可靠性和正确性。
这是TCP成为一种可靠传输协议的关键之一。
tcp伪首部格式摘要:1.TCP 协议概述2.TCP 伪首部的概念和作用3.TCP 伪首部格式4.TCP 伪首部的应用5.结论正文:1.TCP 协议概述TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
TCP 协议负责在通信双方建立稳定的连接,保证数据包的可靠传输,以及数据的正确顺序。
在我国,TCP 协议被广泛应用于互联网、局域网等各类网络环境中。
2.TCP 伪首部的概念和作用TCP 伪首部(TCP Pseudo Header)是TCP 协议中的一个重要概念。
它实际上并不是真正的首部,而是一个数据结构,用于描述TCP 报文的传输过程。
TCP 伪首部主要包括以下字段:源地址、目标地址、序列号、确认号、窗口大小、检查和、紧急指针、选项等。
这些字段在TCP 报文的传输过程中起到关键作用,如流量控制、拥塞控制、错误检测等。
3.TCP 伪首部格式TCP 伪首部格式如下:- 源地址(Source Address):表示发送方的IP 地址。
- 目标地址(Destination Address):表示接收方的IP 地址。
- 序列号(Sequence Number):表示数据包在发送端的序列,用于接收端排序。
- 确认号(Acknowledgment Number):表示接收端期望接收到的下一个数据包的序列号。
- 窗口大小(Window Size):表示接收端当前的接收缓冲区大小,用于流量控制。
- 检查和(Checksum):用于检测数据包在传输过程中的错误。
- 紧急指针(Urgent Pointer):用于标识紧急数据。
- 选项(Options):可选字段,如最大报文段长度(Maximum Segment Size)、时间戳(Timestamps)等。
4.TCP 伪首部的应用TCP 伪首部在TCP 协议中具有重要作用,主要体现在以下几个方面:- 流量控制:通过窗口大小字段,接收端可以告知发送端自己的接收能力,从而避免数据溢出。
中文算法伪代码概述在计算机科学中,算法是解决问题的方法和步骤的描述,而伪代码则是一种类似于编程语言的抽象描述方式。
中文算法伪代码指的是用中文语言描述算法的伪代码,相比其他语言的伪代码,它更便于理解和使用。
本文将从以下几个方面详细探讨中文算法伪代码。
为什么需要中文算法伪代码对于非专业的程序员或计算机科学领域的新手来说,掌握一门编程语言的语法和规则可能是一项具有挑战性的任务。
而使用中文算法伪代码,可以将复杂的编程概念用更简单易懂的中文语言进行描述,极大地降低了学习和理解的难度。
此外,中文算法伪代码还可以方便非程序员之间的沟通和交流,使得更多人能够参与到算法设计和问题解决中。
中文算法伪代码的语法规则中文算法伪代码的语法规则主要包括以下几个方面:关键字与其他编程语言类似,中文算法伪代码也有一些关键字用来表示不同的操作和控制结构,例如「如果」、「那么」、「否则」等。
这些关键字用来描述算法的逻辑流程和条件判断。
注释中文算法伪代码的注释使用「注释:」关键字进行标识,以帮助读者理解代码的意图和目的。
注释可以用来解释算法中的特殊处理或者对某段代码的说明。
变量和赋值中文算法伪代码可以使用中文词语作为变量名,程序员可以根据实际情况选择合适的命名方式。
赋值操作使用「赋值给」的关键字进行表示,例如「x 赋值给 5」表示将 x 的值设置为 5。
控制结构中文算法伪代码支持常见的控制结构,例如条件判断、循环和函数定义等。
条件判断使用「如果」、「那么」和「否则」关键字进行表示;循环使用「重复」和「直到」关键字进行表示;函数定义使用「定义」和「为」关键字进行表示。
函数调用中文算法伪代码可以使用函数调用来实现代码的模块化和重用。
函数调用使用「调用」和「函数名」进行表示,例如「调用求和函数」表示调用名为「求和函数」的函数。
示例中文算法伪代码下面是一个计算斐波那契数列的算法的示例中文算法伪代码:从键盘输入一个正整数 n如果 n 小于等于 0则输出错误信息并结束否则定义函数求斐波那契数列如果 n 等于 1 或者 n 等于 2则返回 1否则返回求斐波那契数列(n-1) 加上求斐波那契数列(n-2)调用求斐波那契数列函数并输出结果结束在以上示例中,使用了中文关键字来描述算法的逻辑流程,使得代码更加易懂。
tcp伪首部格式
TCP伪首部是用于计算TCP报文段校验和的辅助数据结构。
它包含了TCP报文段的一些关键信息,如序号、确认号等。
以下是TCP伪首部的详细格式:
-源端口号(16比特):标识发送方应用进程的端口号。
-目的端口号(16比特):标识接收方应用进程的端口号。
-序列号(32比特):表示数据载荷中第一个字节的序号。
每个TCP 报文段的数据都按照序号依次发送。
-确认号(32比特):表示期望接收方下一个TCP报文段的数据载荷的第一个字节的序号。
同时,它也是对之前收到的所有数据的确认。
-数据偏移(4比特):表示TCP报文段数据载荷部分的起始处距离TCP报文段起始处有多远,以4字节为单位。
-保留字段(4比特):始终设置为0。
-标志位(16比特):包括URG、ACK、PSH、RST、SYN、FIN等标志,用于表示TCP报文段的特点。
-窗口大小(16比特):表示接收方缓冲区大小,用于通知发送方可以发送的数据量。
-校验和(16比特):用于检测TCP报文段在传输过程中的错误。
-紧急指针(16比特):指向TCP报文段中紧急数据的位置。
需要注意的是,在实际传输过程中,TCP伪首部中的序列号、确认号等字段会随着数据传输而不断变化。
在计算校验和时,需要根据实际情况更新这些字段。
此外,窗口大小字段在传输过程中,发送方和接收方的窗口大小可能会发生变化,也需要在计算校验和时进行适当的调整。
套接字:通信端点16.2.1 什么是套接字套接字是一种具有之前所说的“通信端点”概念的计算机网络数据结构。
网络化的应用程序在开始任何通讯之前都必需要创建套接字。
就像电话的插口一样,没有它就完全没办法通信。
套接字起源于20世纪70年代加州大学伯克利分校版本的Unix,即人们所说的BSD Unix。
因此,有时人们也把套接字称为“伯克利套接字”或“BSD套接字”。
一开始,套接字被设计用在同一台主机上多个应用程序之间的通讯。
这也被称作进程间通讯,或IPC。
套接字有两种,分别是基于文件型的和基于网络型的。
Unix套接字是我们要介绍的第一个套接字家族。
其“家族名”为AF_UNIX(在POSIX1.g标准中也叫AF_LOCAL),表示“地址家族:UNIX”。
包括Python在内的大多数流行平台上都使用术语“地址家族”及其缩写“AF”。
而老一点的系统中,地址家族被称为“域”或“协议家族”,并使用缩写“PF”而不是“AF”。
同样的,AF_LOCAL(在2000-2001年被列为标准)将会代替AF_UNIX。
不过,为了向后兼容,很多系统上,两者是等价的。
Python自己则仍然使用AF_UNIX。
由于两个进程都运行在同一台机器上,而且这些套接字是基于文件的。
所以,它们的底层结构是由文件系统来支持的。
这样做相当有道理,因为,同一台电脑上,文件系统的确是不同的进程都能访问的。
另一种套接字是基于网络的,它有自己的家族名字:AF_INET,或叫“地址家族:Internet”。
还有一种地址家族AF_INET6被用于网际协议第6版(IPv6)寻址上。
还有一些其他的地址家族,不过,它们要么是只用在某个平台上,要么就是已经被废弃,或是很少被使用,或是根本就还没有实现。
所有地址家族中,AF_INET是使用最广泛的一个。
Python 2.5中加入了一种Linux套接字的支持:AF_NETLINK(无连接(稍后讲解))套接字家族让用户代码与内核代码之间的IPC可以使用标准BSD套接字接口。
中文算法伪代码
中文算法伪代码是一种用中文语言来描述的程序设计语言,类似于人类语言,可以更加直观地展现程序的执行过程。
下面,本篇文章将简要介绍如何编写一个简单的中文算法伪代码。
第一步:确定问题
在编写算法之前,我们首先要明确问题的具体内容,这有助于我们更加准确地描述算法。
例如,我们要设计一个用于求解1~100之间所有奇数之和的算法。
第二步:流程设计
在明确问题之后,我们可以开始设计算法的流程。
以求1~100奇数之和为例,算法的流程可按照以下步骤进行:
1. 定义一个变量sum,初始值为0。
2. 从1开始,依次遍历1~100之间的所有数。
3. 对于遍历到的每一个数,判断是否为奇数,如果是,则将该数加到sum中。
4. 遍历完所有数后,输出sum的值。
我们可以看到,这个算法的流程十分简单明了,易于理解。
第三步:伪代码描述
在明确流程之后,我们可以使用中文算法伪代码来描述程序的执行流程。
该算法的中文伪代码如下:
sum = 0
for i = 1 to 100 do
if i mod 2 = 1 then
sum = sum + i
end if
next i
print sum
在这段伪代码中,变量sum代表奇数之和,通过for循环遍历1~100的所有数,并通过if语句判断是否为奇数,如果是,则将该数加到sum中,并最终输出sum的值。
总结:
中文算法伪代码是一种易于理解的程序设计语言,可以帮助开发者更加直观地展现程序的执行流程,提高程序设计与开发效率。
对于初学者来说,学习中文算法伪代码是一个不错的选择。
基于NS-2的FAST TCP协议快速收敛改进算法摘要:FAST TCP协议采用静态表映射方法设置慢启动阈值,在复杂多变的网络环境无法实现快速收敛。
本文首先通过NS-2仿真实验发现了慢启动阈值与系统收敛速度的关系,然后采用数学方法理论分析了慢启动阈值对与系统收敛速度的影响,并根据上述实验和理论分析结果,提出了一种动态设置慢启动阈值的改进算法。
该算法将各连接留在链路缓冲区的个数作为慢启动阈值量纲,根据各连接实际的协议参数确定慢启动阈值,使其在复杂多变的网络环境下获得较好的收敛性能。
NS-2仿真结果表明该算法的有效性。
1 FAST TCP简介FAST TCP是一种面向高带宽延时积网络的新型TCP拥塞控制协议。
它从根本上改变了传统TCP的拥塞控制机制。
该协议是由加州理工学院网络实验室Steven H.Low 等人在源端针对高速、长时延、大容量的高性能网络提出的一种新型高速传输控制协议。
FAST TCP 协议完全将拥塞控制器建立在各连接源端,采用估测的排队时延作为拥塞反馈信号,其基于平衡的设计思想使其稳定性、吞吐量、公平性和快速响应等性能指标要优于TCP Reno、HSTCP和STCP等网络传输控制协议。
但其存在难以选择确保系统稳定的协议参数和准确估计传播延时等公开问题。
这些公开问题阻碍了该协议的进一步推广。
2 FAST TCP所存在的问题通过分析FAST TCP代码(由澳大利亚墨尔本大学CUBINLAB实验室网页.au/ns2fasttcp/ 提供)和文献[1,2,4]可知,FAST TCP在建立新连接时,是采用静态表映射方法初始化FAST TCP的协议参数α、控制律增益参数g和慢启动阈值m,各取值分别为200、0.5和0.00075。
这种静态表映射的方法存在致命的缺陷,就是无法很好的适应变化层出不穷的网络拓扑。
下面我们通过一组对比实验说明此问题。
我们通过NS-2网络仿真平台,搭建如图1的经典哑铃网络系统:哑铃网络系统中包含3条具有相同链路属性的FAST TCP 连接,共享唯一瓶颈链路l 。
文章标题:深入解析MATLAB中TCP客户端(tcpclient)的用法在MATLAB中,TCP客户端(tcpclient)是一种用于与远程服务器进行通信的工具。
在本文中,我们将深入探讨TCP客户端的使用方法,并共享一些个人观点和理解。
1. TCP客户端简介TCP客户端是一种用于与远程服务器进行TCP/IP通信的MATLAB工具。
通过TCP客户端,用户可以与远程服务器建立连接,并发送和接收数据。
这种通信方式通常用于实时数据传输、远程控制等应用场景。
2. 创建TCP客户端对象在MATLAB中,可以通过以下代码创建一个TCP客户端对象:```matlabtcpClient = tcpclient('serverIP', port);```其中,'serverIP'是远程服务器的IP位置区域,port是服务器开放的端口号。
通过这样创建的tcpClient对象,我们可以进行后续的通信操作。
3. 连接服务器一旦创建了tcpClient对象,就可以使用connect方法连接到远程服务器:```matlabconnect(tcpClient);```通过连接到服务器,我们可以开始与服务器进行数据交换。
4. 发送和接收数据使用TCP客户端,我们可以使用write和read方法向服务器发送数据并接收数据。
例如:```matlabwrite(tcpClient, data);responseData = read(tcpClient);```上述代码中,我们通过write方法向服务器发送了数据data,并使用read方法接收服务器返回的响应数据。
通过这种方式,可以实现双向数据交换。
5. 关闭连接在通信结束后,需要通过close方法关闭与服务器的连接:```matlabclose(tcpClient);```通过关闭连接,可以释放资源并结束通信。
通过以上步骤,我们可以使用MATLAB中的TCP客户端实现与远程服务器的通信。
关于TCP伪造IP的
关于TCP伪造IP的一个问题,高手指导!最近在看TCP协议伪造IP的文章,有个地方不太明白,请高手指导!谢谢!
主机X伪造IP地址步骤如下:首先,X冒充A,向主机B发送一个带有随机序列号的SYN包。
主机B响应,向主机A发送一个带有应答号的SYN+ACK包、该应答号等于原序列号加1。
同时,主机B 产生自己发送包序列号,并将其与应答号一起发送。
为了完成三次握手,主机X需要向主机B回送一个应答包,其应答号等于主机B向主机A发送的包序列号加1。
假设主机X与A和B不同在一个子网内,则不能检测到B的包,主机X只有算出B的序列号,才能创建TCP连接。
其过程描述如下:
X→B:SYN(序列号=M),SRC=A
B→A:SYN(序列号=N),ACK(应答号=M+1)
X→B:ACK(应答号=N+1),SRC=A
按上边说的,如果X伪造一个应答包发送给B,那么其中包含的应答好N+1,这个N从哪可以得到?这个序列号N,B是发给真是的主机A了啊?。
TCP超时设置 在学习TCP超时设置的时候,发现⽹上没有完整的超时介绍,遂总结⼀下。
TCP超时总共分为3类:connectTimeout, writeTimeout, readTimeout(连接超时,读超时,写超时)。
下⾯分别介绍如何设置这三种超时。
1. 连接超时 在TCP调⽤connect函数时,TCP的建⽴需要3次握⼿,从客户端发出SYS信号之后开始等待,超过超时时间即连接失败,connect函数不再等待,直接返回。
这个时间称为超时时间。
超时时间系统是有最⼤限制的,以Linux系统为例,调⽤命令:sysctl net.ipv4.tcp_syn_retries可以查看系统设置的connectTimeout最⼤值。
返回值:4:timeout是31s5: timeout是75s6: timeout是127s但是有时我们希望设置⾃⼰的connectTimeout时间(注:此时间必须⽐系统timeout时间短,否则系统会截成系统timeout时间)。
1.1 使⽤alarm函数在设置超时时间时,可以采⽤alarm函数,具体如下://超时处理函数void alarm_handler(int sig){printf("connect timeout");return;}int main(){...signal(SIGALRM, alarm_handler)alarm(5); //设置超时时间5sint rc=connect(...); //调⽤connect函数alarm(0);if(rc<0){if(errno==EINTR){//connect超时 }}}这种⽅法可能有以下缺陷:(1) 有些UNIX操作系统在信号处理程序返回之后可能重启connect调⽤;(2) 假如connect成功,但是此时alarm定时到了,此时程序仍然会终⽌。
1.2 使⽤select函数使⽤select函数,监听套接字是否有读或写性质的变化(实际上监视写性质的变化就⾏了,因为⼀旦连接成功,套接字⼀定是可写的)。
TCP创造并发展于1970年代~1980年代,这注定了它能工作但脆弱。
在TCP伊始,最重要的是可用,而不是高效,也不是安全,因此,在端到端TCP连接的中间,利用伪造的ACK,你很容易完成一种叫做中间人攻击的事情。
如果你用“TCP劫持”,“TCP中间人”,“TCP注入”等作为关键词百度或者Google,绝大部分内容都在SYN报文上做文章,诸如会话Reset,会话劫持,SYN Flood攻击等等,但实际上还有更好玩的恶作剧。
通过在中间路径上伪造ACK,你可以:提前确认数据,扰乱TCP的ACK时钟,影响RTT测量。
由于数据尚未到达receiver,提前伪造的ACK可以造成sender测量的RTT偏短,误导其BDP的测量。
乱序确认数据,扰乱ACK到达模式,影响拥塞控制。
比方说倒序发送两个伪造的ACK,可以造成sender端burst数据引发拥塞(ABC机制可减缓)。
确认已经丢弃的数据,接收端空洞永无可弥补。
只要sender收到ACK,数据就会从重传队列中永久删除,但事实上这个ACK是伪造的,真正的数据已经丢失。
receiver将再也无法等到这个数据。
确认已经丢弃的数据,伪造数据弥补空洞实现注入。
参照上面一点,既然receiver在苦等再也等不到的数据,中间人便可以伪造任意数据去填补这个空洞,实现数据注入。
伪造数据注入,使SSH,HTTPS等解密失败,TCP正常关闭。
参照上面两点伪造数据注入HTTPS,SSH等加密连接,会造成解密失败,从而应用程序调用close关闭连接不是Reset掉连接。
是不是更有趣呢?特别是最后一点,大多数时候,程序员,运维以及经理在排查TCP问题的时候,总是盯着Wireshark里显示成红色的RST报文,现在他们有能力通过IPID字段的分布以及TTL字段判断该RST是不是来自中间设备了(几年前他们还做不到…)。
然而,我让连接断开的方式并没有使用过时的RST,而是注入脏数据,序列号,IPID,TTL等均匹配,这样会很大程度扰乱程序员,运维和经理们的思路,让他们加班到头昏脑胀的时候陷入更加炼狱般的深渊。
TCP/IP通信程序之伪代码
UDP发送程序如下:
1.用WSAStartup函数初始化Socket环境;
2.用socket函数创建一个套接字;
3.用setsockopt函数设置套接字的属性,例如设置为广播类型;很多时候该步骤可以省略;
4.创建一个sockaddr_in,并指定其IP地址和端口号;
5.用sendto函数向指定地址发送数据,这里的目标地址就是广播地址;注意这里不需要绑定,即使绑定了,其地址也会被sendto中的参数覆盖;若使用send函数则会出错,因为send是面向连接的,而UDP 是非连接的,只能使用sendto发送数据;
6.用closesocket函数关闭套接字;
7.用WSACleanup函数关闭Socket环境。
UDP接收程序如下,注意接收方一定要bind套接字:
1.用WSAStartup函数初始化Socket环境;
2.用socket函数创建一个套接字;
3.用setsockopt函数设置套接字的属性,例如设置为广播类型;
4.创建一个sockaddr_in,并指定其IP地址和端口号;
5.用bind函数将套接字与接收的地址绑定起来,然后调用recvfrom
函数或者recv接收数据;注意这里一定要绑定,因为接收报文的套接字必须在网络上有一个绑定的名称才能保证正确接收数据;
6.用closesocket函数关闭套接字;
7.用WSACleanup函数关闭Socket环境。
TCP服务器程序:
1.用socket函数创建一个套接字sock;
2.用bind将sock绑定到本地地址;
3.用listen侦听sock套接字;
4.用accept函数接收客户方的连接,返回客户方套接字clientSocket;
5.在客户方套接字clientSocket上使用send发送数据;
6.用closesocket函数关闭套接字sock和clientSocket;
客服端程序如下:
1.用socket函数创建一个套接字sock;
2.创建一个指向服务方的远程地址;
3.用connect将sock连接到服务方,使用远程地址;
4.在套接字上使用recv接收数据;
5.用closesocket函数关闭套接字sock;。