厦门高端网站建设关于网站开发的

web/2025/10/4 14:46:06/文章来源:
厦门高端网站建设,关于网站开发的,wordpress crm 主题,淘宝店网站建设总言 主要内容#xff1a;传输层UDP、TCP协议基本介绍。UDP报文格式、TCP报文格式、三次握手四次挥手、TCP可靠性策略说明。 文章目录 总言8、UDP协议#xff08;传输层一#xff09;8.1、传输层预备知识8.1.1、端口号8.1.2、一些指令#xff08;netstat、pidof、xargs传输层UDP、TCP协议基本介绍。UDP报文格式、TCP报文格式、三次握手四次挥手、TCP可靠性策略说明。 文章目录 总言8、UDP协议传输层·一8.1、传输层预备知识8.1.1、端口号8.1.2、一些指令netstat、pidof、xargs 8.2、UDP报文8.2.1、基本认识8.2.2、细节理解 9、TCP协议传输层·二9.1、初步理解9.1.1、首要解决的两个问题16位目的端口号、四位首部长度9.1.2、理解什么叫做可靠性9.1.3、32位序号和32位确认序号 9.2、其它TCP报头属性9.2.1、16位窗口大小与流量控制(引入篇)9.2.2、6位标志位9.2.3、其余报头简述 9.3、TCP的三次握手和四次挥手9.3.1、如何理解连接9.3.2、如何理解三次握手9.3.2.1、基本描述9.3.2.2、细节理解 9.3.3、如何理解四次挥手9.3.3.1、基本描述9.3.3.2、细节理解 9.4、TCP可靠性的其他策略9.4.1、确认应答(ACK)机制9.4.2、超时重传机制9.4.3、流量控制9.4.4、滑动窗口 快重传9.4.5、高速重发机制快重传9.4.6、慢启动机制 拥塞窗口9.4.7、延迟应答9.4.8、捎带应答 9.5、其它问题说明9.5.1、面向字节流9.5.2、数据报粘包问题9.5.3、TCP异常9.5.4、 listen 的第二个参数 8、UDP协议传输层·一 8.1、传输层预备知识 8.1.1、端口号 1、什么是端口号   说明端口号(Port)标识了一个主机上进行通信的不同的应用程序。 在TCP/IP协议中, 用 “源IP”、“源端口号”、“目的IP”、“目的端口号”、“协议号” 这样一个五元组来标识一个通信(可以通过netstat -n查看显示所有已建立的有效连接。); 2、端口号范围划分   0 - 1023: 知名端口号, HTTP, FTP, SSH等这些广为使用的应用层协议, 他们的端口号都是固定的。 1024 - 65535: 操作系统动态分配的端口号. 客户端程序的端口号, 就是由操作系统从这个范围分配的。         说明为了使用方便, 人们约定一些常用的服务器, 都是用以下这些固定的端口号。在/etc/services文件中可查看。 ssh服务器, 使用22端口 ftp服务器, 使用21端口 telnet服务器, 使用23端口 http服务器, 使用80端口 https服务器, 使用4433、问题说明   问题一 一个进程是否可以bind多个端口号?   回答可以。之前套接字学习中创建套接字会分配sockefd相当于网络中的一个连接就是一个文件。因为一个进程可以打开多个文件描述符所以一个进程可以绑定多个端口号。         问题二 一个端口号是否可以被多个进程bind?   回答原则上不可以。如果一个进程先绑定一个端口号然后再fork一个子进程这样的话就实现了多个进程绑定一个端口号。但是不同的进程绑定同一个端口号是不可以的实际上当服务器挂掉不能立即重启(TIME_WAIT状态)也说明不用进程不能同时绑定同一个端口号。         问题三为什么不直接使用进程PID来代替端口号识别唯一的进程   回答①不是所有的进程都要对外提供网络服务如果直接使用进程pidOS还需要筛选到底是哪些进程参与提供网络服务增添筛选成本。②为了让系统功能和网络功能解偶联。             8.1.2、一些指令netstat、pidof、xargs 1、netstat   netstat是一个用来查看网络状态的重要工具。Netstat会显示与IP、TCP、UDP和ICMP协议相关的统计数据一般用于检验本机各端口的网络连接情况。   语法netstat [选项]   功能查看网络状态   常用选项 -n 拒绝显示别名能显示数字的全部转化成数字 -l 仅列出有在 Listen (监听) 的服务状态 -p 显示建立相关链接的程序名 -t (tcp)仅显示tcp相关选项 -u (udp)仅显示udp相关选项 -a (all)显示所有选项默认不显示LISTEN相关常用-nltp、-antp.               2、pidof   语法 pidof [进程名]   功能 通过进程名, 查看进程id      以下为简单演示通过这种方法可以很快的查看自己写的进程。 3、xargs   相关指令介绍见常见指令入门二。 一个小演示文件日期更新。 [wjVM-4-3-centos http_demo]$ ls -al #原先文件日期 total 36 drwxrwxr-x 3 wj wj 4096 Nov 12 21:59 . drwxrwxr-x 4 wj wj 4096 Nov 11 20:11 .. -rw-rw-r-- 1 wj wj 2894 Nov 12 21:40 HttpServer.cc -rw-rw-r-- 1 wj wj 1667 Nov 11 11:02 HttpServer.hpp -rw-rw-r-- 1 wj wj 1107 Nov 11 11:02 Log.hpp -rw-rw-r-- 1 wj wj 98 Nov 11 11:02 Makefile -rw-rw-r-- 1 wj wj 4043 Nov 11 11:02 Sock.hpp -rw-rw-r-- 1 wj wj 1334 Nov 11 19:41 Util.hpp drwxrwxr-x 5 wj wj 4096 Nov 11 18:47 wwwroot [wjVM-4-3-centos http_demo]$ ls | xargs touch [wjVM-4-3-centos http_demo]$ ls -al #更新后的文件日期 total 36 drwxrwxr-x 3 wj wj 4096 Nov 12 21:59 . drwxrwxr-x 4 wj wj 4096 Nov 11 20:11 .. -rw-rw-r-- 1 wj wj 2894 Nov 19 09:37 HttpServer.cc -rw-rw-r-- 1 wj wj 1667 Nov 19 09:37 HttpServer.hpp -rw-rw-r-- 1 wj wj 1107 Nov 19 09:37 Log.hpp -rw-rw-r-- 1 wj wj 98 Nov 19 09:37 Makefile -rw-rw-r-- 1 wj wj 4043 Nov 19 09:37 Sock.hpp -rw-rw-r-- 1 wj wj 1334 Nov 19 09:37 Util.hpp drwxrwxr-x 5 wj wj 4096 Nov 19 09:37 wwwroot [wjVM-4-3-centos http_demo]$ 8.2、UDP报文 8.2.1、基本认识 1、UDP协议端格式   问题描述 根据之前学习我们知道数据自上而下交付需要层层封装添加报头。相反自下而上递交数据时需要层层解包去掉报头。那么①UDP协议是如何分离报头or 封装报头的②又是如何将报文交付到某一具体主机的具体进程上 回答以下为UDP协议的基本格式。 1、UDP采用固定长度的报头(8字节)可根据此分离报头和有效载荷。   2、每层协议层报头中存储着当前层的首部属性信息。在UDP报头首部记载着16位的目的端口号可根据此进行向上交付PS无论客服端还是服务端进程使用bind函数时绑定了端口号。因此交付报文时可以找到具体的某一进程。            2、其它问题说明   问题1为什么编写代码时对端口号的类型为uint16_t   回答 OS所决定了协议所使用的端口号就是16位的。因此我们使用时也一并使用uint16_t表示端口号类型。         问题2udp如何正确提取整个完整的报文   回答 报头中有记录报文长度的属性16位UDP长度。   PS在不考虑丢包情况下UDP是具有将报文一个一个正确接受的能力的即面向数据报。          8.2.2、细节理解 1、如何理解报文本身   实际报头也是结构化的字段。例如位段以下为一个简易版的理解草图实际OS会很复杂如需要处理位段的可移植性等各种问题。 2、UDP传输的特点   无连接知道对端的IP和端口号就直接进行传输, 不需要建立连接;   不可靠没有确认机制, 没有重传机制; 如果因为网络故障该段无法发到对方, UDP协议层也不会给应用层返回任何错误信息;   面向数据报不能够灵活的控制读写数据的次数和数量;          对面向数据报的理解 说明 应用层交给UDP多长的报文UDP就原样发送该长度的报文。既不会拆分, 也不会合并。 用UDP传输100个字节的数据:   例如 如果发送端调用一次sendto发送100个字节那么接收端也必须调用对应的一次recvfrom,接收100个字节而不能循环调用10次recvfrom, 每次接收10个字节。            3、UDP缓冲区 理解sent\recvfrom等IO类接口数据 说明IO函数本质是拷贝函数我们实际在使用send/write或者recv/read这类函数时并不是直接把数据发送到网络甚至对方主机而是把我们的数据拷贝到发送/接收缓冲区中。 至于什么时候发?发多少?出错了怎么办?等等此类问题不是应用层来考虑的事而是由由传输层的传输控制协议TCP、UDP决定的。体现该层协议传输控制的特性             理解UDP缓冲区 1、UDP具有接收缓冲区。 但是这个接收缓冲区不能保证收到的UDP报的顺序和发送UDP报的顺序一致。如果缓冲区满了,后续到达的UDP数据就会被丢弃。   2、UDP没有真正意义上的发送缓冲区。 调用sendto会直接交给内核由内核将数据传给网络层协议进行后续的传输动作。 UDP的socket既能读, 也能写即UDP是全双工的。 全双工同时支持读和写 半双工读写操作同一时刻只能进行一项4、UDP数据长度说明   UDP协议首部中有一个16位的最大长度也就是说一个UDP能传输的数据最大长度是64K(包含UDP首部)。而64K在当今的互联网环境下是一个非常小的数字如果我们需要传输的数据超过64K就需要在应用层手动的分包、多次发送并在接收端手动拼装。                      9、TCP协议传输层·二 9.1、初步理解 9.1.1、首要解决的两个问题16位目的端口号、四位首部长度 1、tcp报文格式   说明TCP首部内容很丰富如果不计算选项字段一般来说TCP首部有20字节。 2、如何交付报文   说明根据上述TCP协议段格式报头属性中含有16位源/目的端口号可以告知数据是从哪个进程来到哪个进程去。         3、如何解包 or 封装 要理解该问题首先要理解4位首部长度 首部长度也称数据偏移占4位。它指出了TCP报文段的数据起始处距离TCP报文段的起始处有多远即TCP报文的首部长度。应注意“数据偏移”以4字节为计算单位由于4位二进制数表示的最大十进制数字是15因此数据偏移的最大值是60字节这也是TCP首部的最大字节即选项长度不能超过40字节。 要理解该问题首先要理解4位首部长度 基本步骤如下   1、提取20字节   2、根据标准报头提取4位首部长度L二进制表示需要转换为十进制。检测L× 4 若为20代表报头中没有选项属性报头提取完毕。否则说明存在选项属性读取[L× 4 - 20]字节数据即选项的长度。   3、将20字节的属性和选项都读完剩下的就都是有效载荷了。      PS若观察上述的TCP报文格式可以发现TCP协议没有记录整个报文大小/或者有效载荷大小的字段。                   9.1.2、理解什么叫做可靠性 说明挑一个重要的属性(可靠性)作为讲解tcp的切入点。       1、问题引入   问题一是什么原因造成的数据传输不可靠   回答单纯就是数据传输的距离变长了。         问题二存不存在100%可靠的协议呢?   回答通信双方都无法保证自己作为 “最新发送数据的一方”发送出去的 “最新数据 ” 能被对方收到。但是在局部上对于历史发送的数据可以做到100%可靠正是因为接收到对方发送的数据才有了最新数据的发送作为对接收到的消息的回应。            2、如何做到可靠性(局部)   TCP协议的确认应答机制只要发送方发出的一个报文收到了接收方传回的对应应答就能保证我发出的数据对方收到了。 9.1.3、32位序号和32位确认序号 1、问题引入 问题说明数据包乱序也是造成数据传输不可靠的因素之一。 例如 ①客户端一次可能向服务端发送多个报文就有一个问题发送的顺序不一定是接受顺序。   ②同理服务端可以一次响应多个报文那么客户端就需要确认哪个应答对应哪个请求。 为了解决上述问题我们引入了序号和确认序号。               2、序号和确认序号 基本介绍 序号占4个字节。TCP是面向字节流的在一个TCP连接中传送的字节流中的每一个字节都按顺序编号整个要传送的字节流的起始序号必须在连接建立时设置首部中的序号字段值则是指本报文段所发送的数据的第一个字节的序号。   例如一个报文段的序号是301而数据共100字节这就表明本报文段的数据的第一个字节的序号是301最后一个字节的序号是400。显然下一个报文段如果还有的话的数据序号应当从401开始即下一个报文段的序号字段值应为401。      确认号占4个字节。是期望收到对方下一个报文段的第一个数据字节的序号。   例如B正确收到了A发送过来的一个报文段其序号字段值是501而数据长度是200字节序号501700这表明B正确收到了A发送的到序号700为止的数据。因此B期望收到A的下一个数据序号是701于是B在发送给A的确认报文段中把确认号置为701。       作用说明 根据上述描述可知   1、序号和确认序号将请求和应答进行一一对应。 2、确认序号表示在该序号之前的确认序号所对应的数据对方已经全部收到。并告诉对方下次发送时从确认序号指明的序号发送。 3、二者的存在允许部分确认丢失或者不给应答。例如当前序号为100020003000。若接收到的确认序号为3001则说明前两次1000、2000的请求已经被对方接收到即使代表2001、1001的确认序号丢失/未收到。 4、起到排序作用。因为任何一方都会收到报文报文中会携带序号。如此可以避免数据接收顺序不匹配而导致响应操作无法响应的问题。          为什么要分别使用序号、确认序号两个字段只存在一个序号不行吗 回答tcp协议的工作方式都是全双工的任何通信的一方在发送确认的时候也可能携带新的数据。   如果server即想给对方确认应答又想同时给对方进行发送它的消息。这时候就体现了两个字段的用途。相当于四个字段两个为一组分别服务通讯的一方。由此保障了数据的收发。   PS往往给对方发送消息本身即为应答。          9.2、其它TCP报头属性 9.2.1、16位窗口大小与流量控制(引入篇) 数据发送存在的问题举例①丢包、②乱序、③发送太快或太慢。 对于问题③与UDP不同TCP协议既有发送缓冲区又有接收缓冲区但需要明确的是缓冲区的大小是有限的即若发送/接收端处理数据的速度是有限的。   如果发送端发的太快导致接收端的缓冲区被打满这个时候如果发送端继续发送就会造成丢包继而引起丢包重传等等一系列连锁反应。同理如果数据发送太慢会严重影响效率问题。   为了解决这个问题tcp协议传输双方需要给对方同步自己的接收能力而接收能力由接收缓冲区中剩余空间的大小所决定。 TCP这种根据接收端的处理能力,来决定发送端的发送速度的机制就叫做流量控制(Flow Control)。            tcp报文格式中有一个叫做16位窗口大小的报头字段其作用就是向对方传送自己的接收缓冲区剩余空间大小的。          9.2.2、6位标志位 基本说明不同版本可能存在情况不同这里讲述标准的6位标记位的情况。      1、是什么和为什么   问题一为什么需要多个标记位?   回答服务端会收到大量的不同的报文例如常规报文、建立链接的报文、断开链接的报文、确认报文、等等其他类型的报文。不同报文其所需要做的处理工作各有千秋为了方便区别管理以及进行后续处理使用标记位来标记报文的类型。         问题二各个标记位都是什么含义?   回答标记位实际上是宏。    2、相关介绍 SYN: 请求建立连接。我们把携带SYN标识的称为同步报文段占1位。   例如将SYN标志位置为1服务器收到报文解析后就能知道当前客户端是想要进行连接那么后续的处理操作就顺理成章了。      FIN: 通知对方本端即将关闭我们称携带FIN标识的为结束报文段占1位。当FIN1时表明此报文段的数据已发送完毕并要求释放连接。      ACK: 确认应答标志位。凡是该报文具有应答特征该标志位都会被设置为1。   说明大部分网络报文的ACK都是被设置为1的。但是有些报文的ACK不会被置为1比如第一个链接请求报文原因既然是首个请求报文说明历史上客户端和服务器从来没有法发过数据    URG: 紧急标志位配合16位紧急指针使用。占1位。   说明当URG1时表明紧急指针字段有效。它告诉系统此报文段中有紧急数据应尽快发送相当于高优先级的数据而不要按原来的排队顺序来传送。要与首部中紧急指针字段配合使用。 PSH: 提示接收端应用程序立刻从TCP缓冲区把数据读走。占1位。   说明当两个应用进程进行交互式通信时有时在一端的应用进程希望在键入一个命令后立即就能收到对方的响应。在这种情况下TCP就可以使用 推送push 的操作。这时发送方TCP把PSH置为1并立即创建一个报文段发送出去接收方TCP收到PSH1的报文段就尽快地交付接收应用进程而不用再等到整个缓存都填满了后再向上交付。      RST: 对方要求重新建立连接; 我们把携带RST标识的称为复位报文段。占1位。   说明当RST1时表明TCP连接中出现了严重错误如由于主机崩溃或其他原因必须释放连接然后再重新建立传输连接。RST置为1还用来拒绝一个非法的报文段或拒绝打开一个连接。 9.2.3、其余报头简述 9.3、TCP的三次握手和四次挥手 9.3.1、如何理解连接 因为有大量的客户端将来可能连接服务器所以服务端端一定会存在大量的连接。对于这些连接操作系统也需要对它们进行管理即【先描述在组织!】。因此所谓的连接本质是内核的一种数据结构类型。建立连接成功的时候就是在内存中创建对应的连接对象再对多个连接对象进行某种数据结构的组织。      需要注意的是维护连接是有成本的(内存 cpu)。          9.3.2、如何理解三次握手 9.3.2.1、基本描述 1、总览   相关文章深入浅出TCP三次握手 TCP三次握手是浏览器和服务器建立连接的方式目的是为了使二者能够建立连接便于后续的数据交互传输。   第一次握手客户端发送带有 SYN 标志的连接请求数据包给服务端   第二次握手服务端发送带有 SYNACK 标志的连接请求和应答数据包给客户端   第三次握手客户端发送带有 ACK 标志的应答数据包给服务端(可以携带数据)         2、绘图说明 准备说明所谓的三次握手即TCP连接的建立。最初两端的TCP进程都处于关闭状态之后二者分别创建传输控制块。   对于客户端TCP连接建立是由客户端主动发起的因此称为主动打开连接。   对于服务端属于被动打开的一方其会进入监听状态等待TCP客户进程的连接请求。         后续 第一次握手客户端发送TCP连接请求。 设置SYN1 表示这是SYN握手报文。然后将该 SYN 报文发送给服务端即向服务端发起连接之后客户端处于同步已发送状态SYN-SENT。      第二次握手服务端发送针对TCP连接请求进行确认的报文。 服务端收到客户端的 SYN 报文后根据序列号和反序列号设置 SYN1 和 ACK1表示这是一个SYN握手和ACK确认应答报文最后把该报文发给客户端之后服务端处于同步已接收状态SYN-RCVD。 第三次握手客户端发送确认的确认。 ①客户端收到服务端报文后还要向服务端回应最后一个应答报文设置ACK1 表示这是一个应答报文将完整的报文发送给服务端这次报文可以携带数据之后客户端处于连接已建立状态(ESTABLISHED)。②服务器收到客户端的应答报文后也进入连接已建立状态(ESTABLISHED)。   PS三次握手不一定要保证连接成功客户端只要将ACK发出就会变为ESTABLISHED状态但是只有服务端收到了真正的ACK才会建立真正的连接。         3、注意事项   1、为什么绘制的图解中是斜线的箭头传输   回答在三次握手期间存在时间成本问题。      2、发送的只是SYN、ACK这样的报文字段吗   回答始终要记住双方传输的是完整的报文即包含完整的报头和正文数据可无。             9.3.2.2、细节理解 1、是不是三次握手都一定要保证成功   回答不一定。tcp的可靠性是在建立连接之后。在三次握手期间存在丢包概率前两次由于有应答还能获取反馈最后一次无法保证。            2、三次握手是对客户端服务端都要起效。 这是保障客户端和服务端状态改变的判断依据。 前两次丢包因为有ACK应答可以知晓会根据情况做出后续处理。   对于第三次丢包客户端只要发出报文就会改变状态为ESTABLISHED但它也有可能在中途丢包导致服务端没有收到第三次报文。                  3、为什么要三次握手 问题一一次握手行不行 如下图描述这种场景下客服端可以写一个死循环不断请求连接服务器导致服务器资源充满最终挂掉。 问题二两次握手行不行 如果只进行两次握手那么服务器只能确认客户端的请求。由于存在丢包等问题客户端无法保障每次都能收到应答同理服务器也无法得知当前响应在客户端的接收情况。   这种情况下服务端在返回应答报文后就改变状态进入ESTABLISHED 假如此处客户端因资源阻塞、恶意攻击等原因不断重复发送 SYN 报文请求那么服务器在收到请求后就会建立多个冗余的无效链接浪费TCP服务器的资源仍旧属于SYN洪水问题。          问题三为什么三次握手就行 此外三次握手还保证了站在双方立场上都能够保障全双工能收能发。一次握手、两次握手达不到此目的。 问题四四次握手、五次握手……行不行 9.3.3、如何理解四次挥手 9.3.3.1、基本描述 相关文章深入浅出TCP四次挥手   说明终止一个连接要经过四次握手这是因为TCP连接是全双工的因此每个方向必须单独地进行关闭。    第一次挥手客户端发起FIN报文此时客户端进入FIN_WAIT_1状态。   第二次挥手①服务端接受到FIN 报文后发送ACK应答报文此时服务端进入CLOSE_WAIT状态。②客户端接受到ACK应答报文后进入FIN_WAIT_2状态。      第三次挥手①服务端处理完数据后向客户端发送FIN报文此时服务端进入LAST_ACK状态。②客户端接受到FIN报文后客户端发送应答ACK报文进入TIME_WAIT阶段。   第四次挥手①服务端接受到ACK报文后断开连接处于CLOSED状态。②客户端过一段时间后也就是2MSL后进入CLOSED状态。                9.3.3.2、细节理解 CLOSE_WAIT状态介绍 CLOSE_WAIT对方主动关闭连接或者网络异常导致连接中断这时我方的状态会变成CLOSE_WAIT此时我方要调用close()来使得连接正确关闭。属于被动关闭 1、如果我们发现服务器具有大量的CLOSE_WAIT状态的连接的时候原因是什么?   主要原因应用层服务器写得有bug例如忘了关闭对应的连接sockfd。 客服端和服务端只有完成四次挥手后连接才算真正断开此时双方才会释放对应的连接资源。如果服务器接收到两次挥手后不进行调用close那么服务器端就会存在大量处于CLOSE_WAIT状态的连接。      演示代码如下借助了先前的代码快速演示 #include Sock.hppint main() {Sock sock;int listensock sock.Socket(); // 创建套接字sock.Bind(listensock, 8080); // 绑定端口号sock.Listen(listensock); // 监听while (true){uint16_t clientport;std::string clientip;int sockfd sock.Accept(listensock, clientip, clientport);// 连接if(sockfd 0){std::cout [ clientip : clientport ]# sockfd std::endl;}//这里我们没有关闭套接字 }return 0; }演示结果如下 说明close_wait的危害在于在一个进程上打开的文件描述符超过一定数量时新来的socket连接就无法建立了因为每个socket连接也算是一个文件描述符。报错Too many open files。             TIME_WAIT状态介绍 1、TIME_WAIT我方主动调用close()断开连接收到对方确认后状态变为TIME_WAIT。TCP协议规定TIME_WAIT状态会一直持续2MSL(即两倍的分段最大生存期)以此来确保旧的连接状态不会对新连接产生影响。      相关演示 #include Sock.hppint main() {Sock sock;int listensock sock.Socket(); // 创建套接字sock.Bind(listensock, 9090); // 绑定端口号sock.Listen(listensock); // 监听while (true){uint16_t clientport;std::string clientip;int sockfd sock.Accept(listensock, clientip, clientport);// 连接if(sockfd 0){std::cout [ clientip : clientport ]# sockfd std::endl;}//这里我们没有关闭套接字 std::cout 即将关闭套接字 std::endl;sleep(10);close(sockfd);std::cout 套接字已经关闭 sockfd std::endl;}return 0; }演示结果 2、细节说明主动断开连接的一方要维持一段时间的TIME_WAIT状态。在该状态下连接其实已经释放但是地址信息ip port依旧是被占用的即处于TIME_WAIT状态的连接占用的资源不会被内核立马释放。所以当服务器断开后立即重新启动时经常会看到提示绑定失败。 问题描述 在上述服务器的TCP连接没有完全断开之前不允许重新监听这在某些情况下可能是不合理的。 服务器需要处理非常大量的客户端的连接(每个连接的生存时间可能很短但是每秒都有很大数量的客户端来请求)这个时候如果由服务器端主动关闭连接(比如某些客户端不活跃就需要被服务器端主动清理掉)就会产生大量TIME_WAIT连接。由于我们的请求量很大就可能导致TIME_WAIT的连接数很多。而每个连接都会占用一个通信五元组(源ip、源端口、目的ip、目的端口、协议)其中服务器的ip、端口号、协议是固定的如果新来的客户端连接的ip、端口号和TIME_WAIT状态占用的连接重复了就会出现问题。 解决TIME_WAIT状态引起的bind失败的方法 使用setsockopt()设置socket描述符的选项SO_REUSEADDR为1表示允许创建端口号相同、但IP地址不同的多个socket描述符。 int opt 1;setsockopt(listensock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, opt, sizeof(opt));man setsockopt该函数相关使用介绍setsockopt 函数功能及参数详解。 NAMEgetsockopt, setsockopt - get and set options on socketsSYNOPSIS#include sys/types.h /* See NOTES */#include sys/socket.hint getsockopt(int sockfd, int level, int optname,void *optval, socklen_t *optlen);int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen); 在创建套接字时设置。 // 创建套接字int socket(int domain, int type, int protocol);int Socket(){int listensock socket(AF_INET, SOCK_STREAM, 0);if (listensock 0){logMessage(FATAL, socket:创建套接字失败。%d:%s, errno, strerror(errno));exit(2); // 退出}//设置setsockopt套接字选项int opt 1;setsockopt(listensock,SOL_SOCKET,SO_REUSEADDR | SO_REUSEPORT, opt, sizeof(opt));logMessage(NORMAL, socket:创建套接字成功, listensock:%d, listensock);return listensock; // 将套接字返回给TcpServer中的成员函数_listensock}3、回答为什么 为什么要有TIME_WAIT这一段等待时间 ①可靠地终止 TCP 连接网络是不可靠的一个TCP报文段在传输过程中可能会丢失或者延迟到达因此需要等待一段时间确保双方都已经收到对方的ACK报文段防止出现重复的连接或者错误的连接。②保证让迟来的TCP报文段有足够的时间被识别并丢弃。数据报文可能在发送途中延迟但最终会到达因此要等延时的报文段或尚未处理的报文在通讯双方断开连接前来得及接收并做出处理避免造成数据错乱。 扩展为什么是2MLS 9.4、TCP可靠性的其他策略 9.4.1、确认应答(ACK)机制 1、理解确认应答机制   概念介绍在 TCP 协议中发送方发送数据后接收方需要对数据进行确认应答ACKacknowledge的缩写以确保数据已经被正确接收。 确认应答机制的基本原理 发送方将数据分割成称为TCP段TCP segment的较小单元并为每个段分配一个唯一的序列号。发送方将这些TCP段发送给接收方并启动一个定时器来跟踪每个已发送段的确认。接收方收到TCP段后将按序将它们重新组装成完整的数据流并发送一个确认ACK给发送方。确认中包含接收到的最高序列号表示该序列号之前的所有数据都已正确接收。发送方在接收到确认后会停止相应定时器并继续发送下一个序列号的TCP段。如果发送方在定时器超时之前未收到确认它将重新发送未确认的TCP段。 2、理解序号、确认序号的来由   序列号发送方发送的每个TCP段都包含一些字节的数据TCP为每个数据字节分配一个唯一的编号以进行标识此唯一编号称为TCP序列号。   反序列号每一个ACK都带有对应的确认序列号意思是告诉发送者目前已经收到了哪些数据下一次该从哪里开始发。      PS可以将其想象成字节流式的数组序号代表位置即数组下标位置。      思考问题为什么引入需要序列号和反序列号 相关文章确认应答机制与超时重发机制   回答   1、TCP传输中存在 ①发送端发送的数据丢包、②接收端发送的确认应答ACK丢包或延迟等等各种行为导致发送方和接收方数据在相应时间段内对接不上出现数据重发的现象。   2、虽然源主机可以通过重发数据来提供可靠的传输但对于目标主机而言反复收到相同的数据既浪费网络资源还要耗资源对它处理。所以我们需要一种机制来识别是否已经接收到了这个数据包、又能够判断数据包是否需要接收。   3、因此TCP协议引入序列号按顺序给发送数据的每一个字节8位字节都标上号码的编号序列号的初始值并非为0。而是在建立连接以后由随机数生成。而后面的计算则是对每一字节加一 。接收端查询接收数据TCP首部中的序列号和数据的长度将自己下一步应该接收的序号作为确认应答返送回去以此保证数据的顺序和完整性。 9.4.2、超时重传机制 基本说明 根据上述小节内容可知TCP在发送数据时会设置一个计时器, 若至计时器超时仍未收到数据确认信息则会引发相应的超时或基于计时器的重传操作计时器超时称为重传超时(RTO)。 情况一数据真实丢包 情况二ACK应答丢包导致接收方收到重复数据问题如何设置超时重传的时间 最理想的情况下找到一个最小的时间保证 “确认应答一定能在这个时间内返回”。  但是这个时间的长短随着网络环境的不同是有差异的。如果超时时间设的太长会影响整体的重传效率如果超时时间设的太短有可能会频繁发送重复的包。PS由此我们可知超时时间不能固定在网络好的时候超时时间应该短一些网络不好的时候超时时间应该长一些  TCP为了保证无论在任何环境下都能比较高性能的通信因此会动态计算这个最大超时时间。 Linux中(BSDUnix和Windows也是如此)超时以500ms为一个单位进行控制每次判定超时重发的超时时间都是500ms的整数倍。  如果重发一次之后仍然得不到应答等待 2 × 500 m s 2×500ms 2×500ms 后再进行重传。如果仍然得不到应答等待 4 × 500 m s 4×500ms 4×500ms 进行重传。依次类推 以指数形式递增。累计到一定的重传次数TCP认为网络或者对端主机出现异常强制关闭连接。 9.4.3、流量控制 1、为什么需要流量控制   说明接收端处理数据的速度是有限的如果发送端发的太快导致接收端的缓冲区被打满这个时候如果发送端继续发送就会造成丢包继而引起丢包重传等等一系列连锁反应。因此TCP支持根据接收端的处理能力来决定发送端的发送速度这个机制就叫做流量控制(Flow Control)。   相关视频讲解流量控制 接收端将自己可以接收的缓冲区大小放入 TCP 首部中的 “窗口大小” 字段通过ACK端通知发送端。窗口大小字段越大说明网络的吞吐量越高。  接收端一旦发现自己的缓冲区快满了就会将窗口大小设置成一个更小的值通知给发送端。发送端接受到这个窗口之后就会减慢自己的发送速度。  如果接收端缓冲区满了就会将窗口置为0 这时发送方不再发送数据但是需要定期发送一个窗口探测数据段使接收端把窗口大小告诉发送端。当然接收方也可以主动发送一个窗口更新通知数据段以此发送方可以发送新的数据了。            2、相关问题说明 1、流量控制中第一次发送数据时通讯双方如何知道对方的接收能力 回答 第一次发送数据 ≠ ≠  第一次交换报文。第一次报文交换是在三次握手期间这期间通讯双方是不进行数据交换的但可以在对应报文中附带我方当前的接收能力信息TCP首部中有一个16位窗口字段就是存放了窗口大小信息。       扩展 16位数字最大表示65535是否意味着TCP窗口最大就是65535字节   回答实际上TCP首部40字节选项中还包含了一个窗口扩大因子M实际窗口大小是窗口字段的值左移 M 位;          2、当接收方缓冲区满时后续发送方如何知道什么时候可以再次发送数据 回答通过窗口探测和窗口更新通知。      扩展为什么需要窗口更新通知 假设窗口探测间隔为1s但是窗口立马更新好了此时要等待1s后再进行通信无疑是降低效率的行为。因此设置窗口更新通知可以让接收方在更新接收缓冲区的接收能力后立马通知对方。双重保障的灵活使用                         9.4.4、滑动窗口 快重传 1、滑动窗口是什么基本介绍   问题引入 对每一个发送的数据段都要给一个ACK确认应答收到ACK后再发送下一个数据段。这样做有一个比较大的缺点就是性能较差尤其是数据往返的时间较长的时候。      为解决这个问题TCP引入了窗口这个概念。即使在往返时间较长的情况下它也能控制网络性能的下降。确认应答不再是以每个分段而是以更大的单位进行确认时转发时间将会被大幅度的缩短。也就是说发送端主机在发送了一个段以后不必要一直等待确认应答而是继续发送。 相关机制说明   注意事项   1、当如果数据发出后如若收到确认应答就可以从缓冲区清除这部分数据。如果没有收到确认应答必须在缓冲区保留这部分数据。   2、尽管滑动窗口一次能向对方发送多条数据段但这里一次发送的“多条数据”也是有上限的而这个上限取决于对方当前的接收能力由上一次ACK报文中携带首部信息。换句话说滑动窗口的大小是动态变化的。 2、滑动窗口的完善理解建立一个认知模型 问题一滑动窗口的本质是什么   回答实际滑动窗口在自己的发送缓冲区中属于自己的发送缓冲区中的一部分。而根据之前所学缓冲区是一个类似于数组的结构因此滑动窗口本质就是数组中的一段范围区域以指针或下标表示范围。 问题二滑动窗口一定会右移吗滑动窗口可以为0吗   回答不一定。例如在一段时间内若接收方暂未读取接收缓冲区中的数据而发送方不断发送数据会导致缓冲区有限大小越来越小故发送方读取到ACK报文后下一次的滑动缓冲区会出现左指针/左下标向右偏移右指针/右下标不变的情况。当接收缓冲区存满时会出现滑动窗口为零的情况。         问题三若滑动窗口一直向右滑动是否存在越界问题?   回答不存在。TCP的缓冲区实则是环状结构的会根据实际大小做取模处理。         问题四发送方一次发送多个数据段①若接收方最终都接收到了报文数据但返回时某一个ACK应答报文丢包了是否存在影响②若是发送方发送的报文丢包了呢   回答   对情况①数据包已经抵达ACK丢了。在使用窗口控制时是不需要进行重发的。   对情况②数据包丢失。当某段报文丢失的时候当某一段报文段丢失之后, 发送端会一直收到 1001 这样的ACK, 就像是在提醒发送端 我想要的是 1001一样;如果发送端主机连续三次收到了同样一个 “1001” 这样的应答, 就会将对应的数据 1001 - 2000 重新发送;这个时候接收端收到了 1001 之后, 再次返回的ACK就是7001了(因为2001 - 7000)接收端其实之前就已经收到了, 被放到了接收端操作系统内核的接收缓冲区中。这种机制也被称为 “高速重发控制” 。 9.4.5、高速重发机制快重传 说明快速重传Fast Retransmission是一种提高TCP性能的重传策略。当接收方连续收到三个相同序号的确认报文Duplicate ACKs时发送方会认为对应的数据包发生了丢失。为了尽快补发丢失的数据包发送方会立即进行重传而不再等待重传计时器超时。这种方法可以减小因数据包丢失导致的延迟。         思考问题既然有快重传为什么还需要超时重传快重传与超时重传的区别   回答只有收到三个及三个以上相同序号的确认报文时才会触发快速重传因此可能存在以下情况①因各种原因如接收方当前接受能力少于三个报文导致当前发送的多个报文段少于三个时不满足快速重传的条件。②若这三个及其以上的确认应答报文丢了无法触发快速重传。此时就需要超时重传二者相辅相成。          9.4.6、慢启动机制 拥塞窗口 1、网络状态带来的问题说明   TCP有了窗口之后可以连续大量的发送数据包。但要知道网络上有很多的计算机若当前的网络状态出现拥堵在不清楚当前网络状态下贸然发送大量的数据很有可能网络状态引起雪上加霜。因此TCP引入慢启动机制先发少量的数据探路摸清当前的网络拥堵状态再决定按照多大的速度传输数据。         问题1 如何知道网络拥塞 少量丢包 VS 大量丢包 少量丢包时可能是当前通讯双方的主机数据传送的问题。 大量丢包时可能是网络出现问题如网络拥塞。类比课程挂科 挂科率极低说明本次考试试卷处于正常水平极大概率下是学生主观因素造成的 若几乎全班都挂了说明本次考试试卷严重超纲属于教学事故任课老师和评阅老师都要承担责任。问题2 网络拥塞是否还能够重传为什么   回答网络拥塞时若再重传数据虽然一个主机传送的数据大小看起来无足轻重但要知道网络中不止一个主机拥塞是对当前区域内所有主机而言的假若这些主机都不分情况一律向拥塞的网络中传送数据就好比交通堵塞的道路不断涌入车辆不利于疏通。            问题3 如何解决网络拥塞问题   慢启动机制和拥塞窗口。            2、解决方案说明   慢启动机制为了防止问题的出现在通信刚刚开始时就会通过“慢启动”的算法得出数值来对发送数量来进行控制。 举例 1、一开始初始化 cwnd 1表示可以传一个 MSS 大小的数据。 2、当收到一个 ACK 确认应答后cwnd 增加 1于是一次能够发送 2 个 3、当收到 2 个的 ACK 确认应答后 cwnd 增加 2于是就可以比之前多发2 个所以这一次能够发送 4 个 4、当这 4 个的 ACK 确认到来的时候每个确认 cwnd 增加 1 4 个确认 cwnd 增加 4于是就可以比之前多发 4 个所以这一次能够发送 8 个。 5、……如此下去即一个指数级别的增长。细节理解同上述始终要有一个宏观角度网络中主机不止一台一个主机的慢启动机制所带来的效果微乎其微但所有主机遵守相同的协议机制网络拥塞时因慢启动机制和拥塞窗口的存在会减少数据量的发送于是就可达到“星星之火可以燎原”的效果。            拥塞窗口拥塞窗口(cwnd)是发送方维护的一个状态变量单台主机一次向网络中发送大量数据时可能会引发网络拥塞的上限值它会根据网路拥堵情况动态调节 ①发送开始的时候定义拥塞窗口大小为1每次收到一个ACK应答拥塞窗口加1②每次发送数据包的时候将拥塞窗口和接收端主机反馈的窗口大小做比较取较小的值作为实际发送的窗口即滑动窗口大小 min(拥塞窗口大小16位窗口大小[对方接收能力] ); 问题说明若拥塞窗口按照上面这样的方式增长是一种指数级别的增长方式。“慢启动” 只是指初始时慢但是增长速度非常快。为了不能让拥塞窗口单纯倍增式增长引入慢启动的阈值当拥塞窗口超过这个阈值的时候不再按照指数方式增长而是按照线性方式增长。 当TCP开始启动的时候慢启动阈值等于窗口最大值;在每次超时重发的时候慢启动阈值会变成原来的一半同时拥塞窗口置回1。 说明拥塞避免算法就是将原本慢启动算法的指数增长变成线性增长本质还是增长阶段只是增长速度缓慢了一些。若这样一直增长下去网络就会慢慢进入拥塞状况于是会出现丢包现象这时就需要对丢失的数据包进行重传。当触发了重传机制也就进入了「拥塞发生算法」慢启动阈值会变成原来的一半同时拥塞窗口置回1。         拥塞窗口变化规则如下①只要网络中没有出现阻塞窗口就会增大②网络中出现阻塞窗口就会减小。                9.4.7、延迟应答 1、为什么需要有延迟应答         2、介绍延迟应答   如果接收数据的主机立刻返回ACK应答这时候返回的窗口可能比较小 假设接收端缓冲区为1M一次收到了500K的数据如果此时立刻应答, 返回的窗口就是500K。但实际上可能处理端处理的速度很快10ms之内就把500K数据从缓冲区消费掉了。在这种情况下接收端处理还远没有达到自己的极限即使窗口再放大一些也能处理过来。如果接收端稍微等一会再应答比如等待200ms再应答那么这个时候返回的窗口大小就是1M。而窗口越大网络吞吐量就越大传输效率就越高我们的目标是在保证网络不拥塞的情况下尽量提高传输效率。      问题那么所有的包都可以延迟应答么?   回答肯定也不是延迟应答也有其规则。数量限制每隔N个包就应答一次。时间限制超过最大延迟时间就应答一次。具体的数量和超时时间依操作系统不同也有差异。一般N取2超时时间取200ms。 延迟应答的另一个便捷之处比如服务端收到客户端的数据后不是立刻回ACK给客户端而是等一段时间(一般最大200ms)这样如果服务端要是有数据需要发给客户端那么这个ACK就和服务端的数据一起发给客户端了这样比立即回给客户端一个ACK节省了一个数据包。   向上述这样的机制即捎带应答。             9.4.8、捎带应答 基本介绍很多情况下客户端服务器在应用层是 “一发一收” 的意味着客户端给服务器发送了一个数据报文服务器也会给客户端回复相应数据若此时ACK搭上顺风车和服务器回应一起回给客户端。类似这样TCP的确认应答和回执数据通过一个包发送的方式叫做捎带应答。    PS如果接受数据立刻返回确认应答就无法实现捎带应答而是将所接受的数据传送应用处理生成返回数据以后在进行发送请求为止。所以捎带应答需要延迟应答一起配合实现提高网络效率通过这种机制可以使收发的数据量减少。      由于捎带应答的存在四次挥手可以合并成三次挥手。 当被动关闭方在 TCP 挥手过程中「没有数据要发送」 并且 「开启了 TCP 延迟确认机制」 那么第二和第三次挥手就会合并传输这样就出现了三次挥手。此时主动关闭的一方会直接从 FIN_WAIT_1 状态转入 TIME_WAIT 状态。 9.5、其它问题说明 9.5.1、面向字节流 1、UDP、TCP协议说明 UDP协议面向数据报当用户消息通过 UDP 协议传输时操作系统不会对消息进行拆分在组装好 UDP 头部后就交给网络层来处理所以发出去的 UDP 报文中的数据部分就是完整的用户消息。也就是每个 UDP 报文就是一个用户消息的边界这样接收方在接收到 UDP 报文后读一个 UDP 报文就能读取到完整的用户消息。      TCP是一种流协议stream protocol这就意味着数据是以字节流的形式传递给接收者的没有固有的”报文”或”报文边界”的概念。   当用户消息通过 TCP 协议传输时消息可能会被操作系统分组成多个的 TCP 报文也就是一个完整的用户消息被拆分成多个 TCP 报文进行传输。这时接收方的程序如果不知道发送方发送的消息的长度也就是不知道消息的边界时是无法读出一个有效的用户消息的用户消息被拆分成多个 TCP 报文后并不能像 UDP 那样一个 UDP 报文就能代表一个完整的用户消息。 2、进一步介绍 对应TCP协议创建一个TCP的socketOS会在内核中同时创建一个 发送缓冲区 和一个 接收缓冲区。 调用write等写入函数时数据会先写入发送缓冲区中。如果发送的字节数太长会被拆分成多个TCP的数据包发出如果发送的字节数太短就会先在缓冲区里等待等到缓冲区此时装入的数据长度差不多或其他合适的时机时再将数据一次性发送出去;接收数据的时候数据也是从网卡驱动程序先到达内核的接收缓冲区然后应用程序可以调用read等函数从接收缓冲区拿数据。 此外TCP的一个连接既有发送缓冲区也有接收缓冲区。那么对于这样一个连接既可以读数据也可以写数据 这个概念叫做 全双工。由于缓冲区的存在TCP程序的读和写不需要一一匹配。 写100个字节数据时, 可以调用一次write写100个字节, 也可以调用100次write, 每次写一个字节;读100个字节数据时, 也完全不需要考虑写的时候是怎么写的, 既可以一次read 100个字节, 也可以一次read一个字节, 重复100次;             9.5.2、数据报粘包问题 1、问题引入   首先要明确, 粘包问题中的 “包” , 是指的应用层的数据包.   由于TCP面向字节流的属性协议头中没有如UDP一样的 “报文长度” 这样的字段但是有一个序号这样的字段。站在传输层的角度TCP是一个一个报文过来的按照序号排好序放在缓冲区中。站在应用层的角度应用程序看到的只是一串连续的字节数据并不知道这一串连续字节是否为一个完整的应用层数据包。 2、解决方法   如何避免粘包问题?    归根结底就是明确两个包之间的边界 1、对于定长的包保证每次都按固定大小读取即可。由于数据报是固定大小 S I Z E SIZE SIZE, 那么就从缓冲区从头开始按照固定长度 S I Z E SIZE SIZE依次读取即可。   2、对于变长的包可以在包头的位置约定一个包总长度的字段从而就知道了包的结束位置。   3、对于变长的包还可以在包和包之间使用明确的分隔符(应用层协议, 是程序员自己来定的只要保证分隔符不和正文冲突即可);             9.5.3、TCP异常 进程终止TCP 的连接信息是由内核维护的所以当服务端的进程崩溃/进程终止后内核需要回收该进程的所有资源 进程控制块中包含文件描述符文件描述符表中有Socket网卡文件因此TCP的连接资源也被释放。内核会发送第一次挥手 FIN 报文后续的挥手过程也都是在内核完成并不需要进程的参与所以即使服务端的进程退出了还是能与客户端完成 TCP四次挥手的过程。      正常关机和进程终止的情况相同关机时会先强制终止进程回收进程资源此时会释放文件描述符内核发送FIN报文进行四次挥手。   PS由于触发四次挥手断开网络连接时我方主机正在关机所以可能四次挥手挥完了以后才关机也有可能没有挥完就关机了。 但是四次挥手有没有挥完是没有问题的我方关机后不再应答对方就会触发超时重传多次重传都没有得到ACK应答对方就会单方面的断开连接释放存储网络连接相关信息的内存。      机器掉电/网线断开被拔掉电源的一方是没有机会向对方发送四次挥手的也就是先有拔网线的行为再有识别检测到TCP连接异常。   对于我方识别到网络发生变化自动关闭连接。   对于对方由于没有进行四次挥手会认为连接还在。①此时若将网络立马恢复发送端发送数据时接受端会识别到连接异常并重新reset连接触发复位报文RST尝试重置连接。对客户端拔掉电立马恢复和服务端掉电立马恢复都一样。②即使没有写入操作TCP自己也内置了一个保活定时器(TCP心跳包)会定期询问对方是否还在如果对方不在也会把连接释放。         PS 应用层的某些协议也有一些这样的检测机制。例如HTTP长连接中也会定期检测对方的状态。   举例简述我们日常使用的微信、QQ并非长期与服务器保持连接在我们不打开APP应用或只是占线但长时间不访问资源时应用层会对这样的长连接进行一定的管理工作如APP保持登录状态但将与服务器的连接处于断开状态(典型的表现QQ头像呈现灰色、离线)用户后续使用时后会自动重建连接关系。                9.5.4、 listen 的第二个参数 1、问题回顾 对服务端其TCP套接字一系列历程如下 初始化服务器socket创建套接字、bind绑定、listen监听 启动服务器accept获取连接、开始进行通讯服务1、accept获取连接要不要参与三次握手过程   回答不需要accept的作用是直接从底层获取已经建立好的链接。也就意味着是连接先建立好然后accept才能获取对应的连接。即即使不使用accept底层也将连接连接好了。      2、如此就有一个问题如果上层来不及调用accept并且对端还来了大量的连接难道所有的连接都应该先建立好吗?   回答并非如此实际这与listen的第二参数有关。 3、在之前学习TCP套接字时将listen的第二参数设置如下状态为什么要这样设置如何理解listen的第二参数 const static int gbacklog 20; //不能太大、也不能太小NAMElisten - listen for connections on a socketSYNOPSIS#include sys/types.h /* See NOTES */#include sys/socket.hint listen(int sockfd, int backlog); 2、正试介绍 是什么 文档解释如下根据文档可知   在linux 2.2 内核之前backlog是指半连接队列syns_queue的长度。   在linux2.2及之后backlog是指已经完全建立连接但是还没有被应用层accetp之前socket所处全连接队列accetp_queue的长度。 具体说明   Linux内核协议栈为一个tcp连接管理使用两个队列:   1. 半链接队列用来保存处于SYN_SENT和SYN_RECV状态的请求   2. 全连接队列accpetd队列用来保存那些处于established状态而应用层没有调用accept取走的请求 全连接队列的长度会受到 listen 第二个参数backlog的影响。 全连接队列满了的时候就无法继续让当前连接的状态进入 established 状态了。                   使用举例 相关演示 演示结果 其它说明为什么该连接队列不能太长也不能太短   连接队列太长会导致请求处理时间过长甚至超时失败。   连接队列太短服务端工作不饱和系统性能没有完全发挥最大程度利用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/86834.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网站的建设和维护的钱接广告的平台

订阅一个CSDN的RSS为例。 1、打开RSS阅读器。 2、设置->新增订阅->手动新增 订阅URL:输入http://articles.csdn.net/api/rss.php?tid1000 (可以先在PC上打开下该网页,发现他是一个xml网页。) 订阅名称:自己起一个名字&…

彩票网站开发的物流网站和数据库建设

一个服务器上跑多个程序是非常常见的现象。 但是这样做后会有一个问题&#xff0c;那就是容易造成 Host 头攻击。host 头(host header或称主机头)攻击&#xff0c;非常常见。比如&#xff0c;在 jsp 中&#xff0c;我们通常可能存在类似下面的代码。 <script type"te…

网站宣传的手段有哪些wordpress网站主修改密码

git如何远程创建分支我不知道有什么办法可以直接在远程创建分支而不需要clone到本地。背景需求我的需求是直接在远程服务器上创建一个分支直接在远程服务器上删除一个分支这期间都不需要clone到本地来。原因是当项目有多个repository的时候其中的部分创建了一个分支&#xff0c…

电子商务网站开发技术解决方案网站建设自查情况

从0配置JAVA项目相关环境 写在最前面一、安装Java的jdk环境1. 下载jdk2. 配置jdk3. 配置环境变量 二、在vscode中配置java运行环境1. 下载VSCode2. 下载并运行「Java Extension Pack」 三、安装mysql1.官网下载MySQL2.开始安装如果没有跳过安装成功 3.配置MySQL Server4.环境变…

网站开发工作图解网页视频下载用什么软件最好

Android应用界面开发第一章学习第三部分####1.导入其它人创建的Android Studio项目(重点在第二部分)首先将下载的Project压缩包解压到自己的AS工程目录比如&#xff1a;工程目录然后打开AS软件&#xff0c;关闭其它工程(close project)&#xff0c;然后准备导入刚才解压的文件夹…

网站开发合作协议合同范本微信小程序是干什么用的

进程管理方式首先我们了解一下php的三种不同的进程管理方式&#xff1a;static&#xff1a;静态管理进程。在启动时&#xff0c;master按照pm.max_children配置fork出对应数量的work进程&#xff0c;即work的进程是固定不变的。dynamic&#xff1a;动态管理进程。在fpm启动时先…

扶贫办门户网站建设管理办法ui设计生成器

一般引脚: sbit beepP2^4; //将单片机的P2.4端口定义为beep.本口用于屏蔽上电后蜂鸣器响 sbit ledP1^0; //将单片机的P1.0端口定义为led&#xff0c;用于点亮LED-D1 sbit DIG1P0^0; //数码管位选1 sbit DIG2P0^1; //数码管位选2P10xFF;//初始化P1引脚全部置高&a…

北京专业制作网站公司吗免费微信网站开发

1.引言 在先前探讨中&#xff0c;我们了解到计算机主机内部的硬件资源需要一种高效管控手段&#xff0c;由此催生了操作系统的诞生。操作系统&#xff08;Operating System&#xff0c;简称OS&#xff09;&#xff0c;是计算机生态系统中不可或缺的核心组件&#xff0c;以其复杂…

网网站建设公司系统开发总结

Linux中的socket 服务端逻辑客户端逻辑c实现c实现服务端持续接收请求多线程实现 UDP实现 参考 服务端逻辑 创建service_sock创建sockaddr_in结构体变量serv_addr&#xff0c;写明端口和ip将socket和结构体绑定监听socket创建客户端sockaddr_in结构体变量clnt_addr接收客户端请…

怎样把自己做的网站上传河南火焰山网站开发禹

EasyJson是Go语言中对象序列化与反序列化的工具&#xff0c;类似Java中的fastjson和Jackson&#xff0c;能快速对对象进行序列化和反序列化&#xff0c;本次介绍一下使用方法。 版本信息&#xff1a; go1.20.2 1&#xff0c;获取源码 # go get go get -u github.com/mailru…

网站建设怎么做账务处理创卫网站 建设 方案

目录 写在开头 socket服务端&#xff08;基础&#xff09; socket客户端&#xff08;基础&#xff09; 服务端实现&#xff08;可连接多个客户端&#xff09; 客户端实现 数据收发效果 写在开头 近期可能会用python实现一些网络安全工具&#xff0c;涉及到许多关于网络…

易购商城网站怎么做啊专门做卫生间效果图的网站

309.最佳买卖股票时机含冷冻期 309. 买卖股票的最佳时机含冷冻期 - 力扣&#xff08;LeetCode&#xff09; dp数组&#xff1a; 模拟状态&#xff1a;买买买 卖 冻卖卖卖 买 卖 dp[i][0] :持有股票 dp[i][1]: 不持有股票&#xff0c;但是之前卖出去的 dp[i][2]: 不持有股票…

南宁网站平台大专动漫设计有出路吗

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 启动工程失败&#xff0c;报错如题&#xff1a; A component required a bean of type gentle.test.Show that could not be found.…

织梦网站后台文章编辑美化代码怎样创建公司网站

介绍 定义了一个Cache结构体&#xff0c;其中使用sync.Map作为底层数据结构来存储缓存项。Set方法用于设置缓存项&#xff0c;指定键、值以及过期时间。Get方法用于获取缓存项&#xff0c;如果缓存项存在且未过期&#xff0c;则返回值和true&#xff0c;否则返回nil和false。方…

建设网站公开教学视频下载做图表用的网站

前言&#xff1a;博主文章仅用于学习、研究和交流目的&#xff0c;不足和错误之处在所难免&#xff0c;希望大家能够批评指出&#xff0c;博主核实后马上更改。 概述&#xff1a; 后续排序按照从上至下或从右至左的顺序进行&#xff0c;具体取决于方向属性的值。WrapPanel 位…

营销网站开发哪家强wordpress副标题的作用

从一篇日记说起我是一个小前端&#xff0c;我有写日记的习惯2020年10月17 天气 晴今天天气不错&#xff0c;心情也跟着好起来了辛辛苦苦加班两个星期终于完成了产品需求&#xff0c;到了要上线的时候了&#xff0c;嘴里也不知不觉哼起了“劳资今晚不加班”的小曲一顿操作猛如虎…

网站空间文件夹网络工程就业前景好吗

直接判断数据过大 相对而言&#xff0c;由2&#xff0c;3&#xff0c;5&#xff0c;7组成的数更少&#xff0c;则先筛选出由2,3,5,7组成的数&#xff0c;再判断这些数中的质数个数即可 #include <iostream> using namespace std; int main() {printf("1903");…

网站买卖交易平台网站制作工具有哪些

104规约从TCP往上&#xff0c;分成链路层和应用层。 如图&#xff0c;APCI就是链路层&#xff0c;ASDU的就是应用层 我们看到报文都是68打头的&#xff0c;因为应用层报文也要交给链路层发送&#xff0c;链路层增加了开头的6个字节再进行发送。 完全用于链路层的报文每帧都只有…

做tcf法语听力题的网站动漫制作专业在广西哪所院校最强

高中那年&#xff0c;我表姐对我说&#xff1a;“不要老想着出去打工赚钱&#xff0c;好好读书&#xff0c;将来肯定有用&#xff0c;也不要想着现在日子长得很&#xff0c;等你像我这样结婚生子后&#xff0c;一天一眨眼就过完了。”当时听了没有多大感觉&#xff0c;如今深以…

企业网站中( )是第一位的。织梦网站怎么做404页面

一、获取当前窗口句柄 1.元素有属性&#xff0c;浏览器的窗口其实也有属性的&#xff0c;只是你看不到&#xff0c;浏览器窗口的属性用句柄&#xff08;handle&#xff09;来识别。 2.人为操作的话&#xff0c;可以通过眼睛看&#xff0c;识别不同的窗口点击切换。但是脚本没长…