女朋友在互联网公司做网站,成都住建局官网住建局,西安模板网站建设套餐,佛山网站建设的公司文章目录 本篇知识需要有TCP协议【中】的知识#xff01;详情点击#x1f447;1.测试一#xff1a;服务器start函数不定义任何行为#xff08;不调用accept#xff09;的三次握手状态变化int listen(int sockfd, int backlog);的backlog参数全连接队列当全连接队列已满详情点击1.测试一服务器start函数不定义任何行为不调用accept的三次握手状态变化int listen(int sockfd, int backlog);的backlog参数全连接队列当全连接队列已满客户端再发起连接会发生什么 2.测试二服务器start函数不定义任何行为不调用close的四次挥手状态变化 本篇知识需要有TCP协议【中】的知识详情点击
TCP协议【中】 1.测试一服务器start函数不定义任何行为不调用accept的三次握手状态变化 连接建立成功和accept无关 三次握手由双方OS完成 在服务器不调用accept的情况下 客户端发起连接 双方建立好链接了 测试一个客户端跑两个客户端程序访问服务器 两个可以三个呢 客户端三个程序都认为建立好连接了 但是服务器认为第三个连接没建立好为什么看下面且连接建立的成本在客户端。 接下来过一段时间再查看状态发现处于SYN_RECV状态的连接没了但是客户端仍认为处于连接中。 服务端不会长时间维护SYN_RECV服务端由于是全连接队列满而丢弃ack包进入established状态而是处于SYN_RECV状态。由于服务端不会长时间维护SYN_RECV所以过一段时间就会释放半连接即一个syn包不会长时间处于半连接队列隔一段时间还未进入全连接队列的syn包就会被移出半连接队列
像上面服务端处于SYN_RECV或服务端直接释放了半连接而客户端仍处于established状态这种场景 就是 CS双方认为连接不一致 场景服务端处于SYN_RECV一段时间后会释放半连接但客户端认为处于链接此时客户端向S发讯息。 此时信息不是真正的发到网络了而是存入发送缓冲区此时的行为是客户端重新发送syn包接着情况就和上面一样服务端仍会处于SYN_RECV 还有一种场景 服务端已经关闭 客户端仍认为连接成功 但是发消息connect函数已经无法调用成功了 客户端连接结构体对象还没释放 再谈syn洪水 客户端发大量synS由于全连接满而把syn放在半连接队列不拿出来由于半连接队列有长度和时间限制所以这个维度上不会浪费太多资源但是一些无意义的连接占用半连接资源真正想访问服务器的链接进来却无法进入半连接队列或在半连接队列待着不被取走。— 抢课/抢票进不去 // 转圈转半天404了 // 转圈转半天进去了 》服务器有没有处理你的syn请求 backlog不能太大 没必要太大不利场景太大大量请求服务器上层处理不过来全连接队列还满且一直有连接过来这些在全连接队列的连接既占用资源还不创造价值不如不让他们进来。 backlog不能没有 如果没有当上层处理完正在处理的连接却发现底层没有连接可使用 — 上层处理连接的资源没有充分得到利用。如果我们有这样一个队列他存了一些待accept的连接那么当上层处理完当前连接就有连接可以继续处理 — 提高层处理连接的资源的利用率 backlog的大小的影响因素 backlog的确定因素及其大小通常与不同的上下文和应用场景相关。以下是从不同角度对backlog的详细解释和归纳
定义和背景 backlog在计算机和网络领域中特别是在Linux操作系统和TCP/IP协议栈中通常指的是一个队列用于存放等待处理的连接请求或任务。 backlog在PHP-FPM、Nginx和Redis等应用中也有类似的配置用于处理高并发场景下的连接请求。 确定因素 应用场景backlog的大小取决于应用程序的需求如处理高并发连接的能力、响应速度等。 系统资源系统的处理能力、内存和CPU资源等也会影响backlog的大小设置。 网络条件网络带宽、延迟和丢包率等因素也会影响backlog的设置因为较大的backlog可能会在网络拥堵时导致资源浪费。 协议栈实现不同操作系统和协议栈实现可能对backlog的处理方式有所不同这也会影响backlog的确定。 一般大小 Linux操作系统在Linux操作系统中backlog通常分为SYN队列半连接队列和ACCEPT队列已完成连接队列。SYN队列的长度由系统级别设置如/proc/sys/net/ipv4/tcp_max_syn_backlog而ACCEPT队列的长度可以由应用级别设置如Nginx和PHP-FPM中的backlog配置。 默认值许多应用和系统默认将backlog设置为511如Nginx和PHP-FPM但这并不是一个固定的标准值可以根据实际情况进行调整。 调整策略在高并发场景下可能需要增加backlog的大小以提高系统的处理能力。然而过大的backlog可能会导致系统资源浪费因此需要权衡利弊进行调整。 总结 backlog的大小应该根据具体的应用场景、系统资源和网络条件进行确定和调整。 在Linux操作系统中backlog可以分为SYN队列和ACCEPT队列它们的长度可以分别进行配置。 默认值如511只是一个起点需要根据实际情况进行调整和优化。 需要注意的是backlog的设置并不是孤立的还需要与其他系统参数如文件描述符限制、网络超时设置等进行协调和优化。
int listen(int sockfd, int backlog);的backlog参数
服务端处于listen收到客户端的连接请求时如果连接建立成功服务端就会创建连接结构体对象并且可以选择不把建立好的连接返回应用层即作为accept的返回值这也是为什么上面测试结果中服务器没有调用accept底层却可以建立连接的的解释客户端可以发起多个连接服务端本地就会存在多个建立好但未送到accept的连接怎么办先描述再组织用队列管理底层已经建立好的连接让上层调用accept取走连接底层创建{成功建立好连接的}连接对象放入到队列中上层取 ---- PCModelbacklog参数backlog1表示【底层已经建立好的连接队列】的最大长度【底层已经建立好的连接队列】》全连接队列
全连接队列
在网络编程中特别是在处理TCP连接时经常会遇到两种类型的连接队列全连接队列Completed Connection Queue通常被称为accept队列和半连接队列Incomplete Connection Queue通常被称为SYN队列。这两个队列在TCP三次握手过程中起着关键作用。
半连接队列SYN队列 当客户端向服务器发起TCP连接请求时它会发送一个SYN包。服务器收到SYN包后会将其放入半连接队列中并回复一个SYNACK包给客户端。此时服务器和客户端都还没有完成完整的TCP三次握手。
全连接队列Accept队列 当客户端收到服务器的SYNACK包后会回复一个ACK包给服务器。服务器收到这个ACK包后会将这个连接从半连接队列中移除并放入全连接队列中。此时服务器已经完成了TCP三次握手并等待应用层的accept()系统调用来接受这个连接。
backlog参数 在listen()函数中backlog参数通常用来指定全连接队列的最大长度。但是在一些系统中backlog参数实际上同时影响了半连接队列和全连接队列的大小。具体行为可能因操作系统而异。
队列溢出 半连接队列溢出如果半连接队列满了服务器会丢弃新的SYN包并且客户端可能会收到一个RST包表示连接被重置。 全连接队列溢出如果全连接队列满了服务器不会立即回复ACK包给客户端。这会导致客户端在重传SYNACK包时超时并重试连接。如果重试次数达到上限客户端会放弃连接并可能返回一个连接超时错误。 如何调整队列大小 半连接队列大小在一些系统中可以通过修改内核参数如tcp_max_syn_backlog来调整半连接队列的大小。 全连接队列大小全连接队列的大小通常受listen()函数中的backlog参数影响但也可能受其他内核参数如somaxconn的约束。在某些系统中全连接队列的大小也可能受到系统级别的限制。 注意事项 合理地设置队列大小对于服务器的性能和稳定性至关重要。过小的队列可能会导致连接被拒绝或超时而过大的队列可能会浪费系统资源。 在高并发场景下可能需要考虑使用其他技术如连接池、异步IO等来优化性能。 监控队列长度和连接状态对于及时发现和解决问题非常重要。可以使用工具如netstat、ss等来查看队列长度和连接状态。 解决上面的问题服务器认为第三个连接没建立好 服务器listen的backlog参数设置为1意味着全连接队列长度最大为2客户端发起两个链接CS双方都认为连接建立好了但是第三次C认为好了但是S认为没好原因在于客户端传syn包假设服务端半连接队列未满那么Csyn包进入半连接队列然后服务端状态变为SYN_RECV然后S发synack给CC收到后发ack给S后状态变为established但是由于全连接队列满S收到了ack也不会把syn包入全连接队列满了怎么入而是丢弃ack其实也不是丢弃ack而是不做出对应的响应即把syn入全连接队列收到ack表示C成功手收到了“我”上一条发的消息即上述场景是由于S全连接队列满把第三次ack丢弃因为没有收到ack所以不会进入established而是处于SYN_RECV。
当全连接队列已满客户端再发起连接会发生什么
当全连接队列已满时客户端再发起连接会发生以下情况
客户端连接请求的处理 客户端在发起连接时会首先发送一个SYN报文给服务端。此时如果全连接队列已满服务端会收到这个SYN报文但无法立即将新的连接放入全连接队列中。 服务端的行为 服务端收到SYN报文后会将其放入半连接队列syn queue中并发送ACKSYN报文给客户端作为响应。 当客户端收到这个ACKSYN报文后会发送一个ACK报文给服务端表示已经收到了服务端的响应。 然而如果此时全连接队列仍然已满服务端将不再认为客户端的ACK有效而是会重新发送ACKSYN报文给客户端。这个过程可能会重复多次每次重试的间隔时间会在前一次的基础上翻倍例如1秒、2秒、4秒、8秒等。 重试次数与配置 服务端重新发送ACKSYN报文的次数与net.ipv4.tcp_synack_retries配置有关该值默认是5。这意味着服务端最多会重试5次。 连接失败与清理 如果在多次重试后全连接队列仍然是满的服务端将认为再向客户端发送ACKSYN报文已经失去了意义因此会将这个半连接从半连接队列中删除。此时客户端的连接请求将失败。 配置选项的影响 如果tcp_abort_on_overflow配置为1当全连接队列满时服务端会发送一个reset包给客户端直接废掉这个握手过程和连接。这有助于客户端更快地意识到连接失败。 通常情况下为了应对突发流量建议将tcp_abort_on_overflow设置为0这样服务端会尝试通过重试来缓冲连接请求而不是直接拒绝。 解决策略 当遇到全连接队列满的问题时一种常见的解决策略是增加全连接队列的长度。这可以通过调整应用代码中的backlog值或系统级的somaxconn值来实现。 综上所述当全连接队列已满时客户端的连接请求可能会经历多次重试并最终失败。为了避免这种情况可以考虑优化服务端的配置或调整应用代码来增大全连接队列的长度。
2.测试二服务器start函数不定义任何行为不调用close的四次挥手状态变化 客户端退出 向服务端发送fin 服务端向C发ack后进入CLOSE_WAIT由于没有调用close所以不会从CLOSE_WAIT到LAST_ACK如果服务端没有数据要发送了就会调用close此时一旦调用close就会成为lastack状态客户端接收到fin会变为timewait状态然后客户端会发ack给S一旦发出ack客户端会认为四次挥手完成等待若干时长自动释放。若服务器主动退出则一段时间内服务器会处于timewait状态如果在服务器处于timewait~close期间再次以上次的端口号启动服务器就会出现bind错误的情况因为连接没有彻底断开原来的ip和port仍处于被使用状态而一个端口号只能bind一个进程所以出现错误。 双十一购物节 天狗平台同时有大量客户端处于连接访问中 由于客户端太多 使得服务器垮掉 此时服务器主动退出 此时服务器就处于timewait状态30~60s不等由底层和应用层共同控制购物节交易量很大天狗想赚钱。就得立即启动服务器但是他无法启动因为原来的端口仍处于使用状态他不想等30 ~ 60秒就得换个端口但是像这种官方知名网站IP和端口号一般都是公开的也不好更改怎么办setsockopt setsockopt使得即使服务器处于timewait状态也要让服务器以原来的端口号启动进程处于timewait状态不影响我重新启动提供服务当然如果端口号不能用是因为在被其他进程使用此时就不能再让一个进程用这个端口号。 客户端主动断开 需不需要setsockopt来使得能够复用端口号 不用客户端的端口号由OS自动分配 不一定非要用上一次得到端口号 而服务器就不一样了 服务器一般绑定一个知名端口 供用户访问 详细了解setcsockopt setsockopt 函数是 Linux 中用于设置套接字选项的系统调用。这个函数允许你修改套接字的行为或特性。下面我将详细解释 setsockopt 函数的参数、返回值、工作原理、函数功能及其作用。
函数原型 c #include sys/socket.h
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen); 参数 sockfd这是一个文件描述符通常是由 socket 函数返回的套接字描述符。 level指定要设置选项的协议级别。常见的值有 SOL_SOCKET基本套接字选项、IPPROTO_TCPTCP 选项、IPPROTO_IPIP 选项等。 optname指定要设置的选项的名称。这个值依赖于 level 参数。例如在 SOL_SOCKET 级别下SO_REUSEADDR 和 SO_KEEPALIVE 是有效的选项名。 optval指向一个包含选项值的缓冲区的指针。这个缓冲区的类型和大小取决于 optname。 optlen指定 optval 缓冲区的大小以字节为单位。 返回值 如果函数成功则返回 0。 如果函数失败则返回 -1并设置全局变量 errno 以指示错误原因。 工作原理 setsockopt 函数通过修改内核中与套接字相关的数据结构来设置选项。当你调用这个函数时内核会检查你提供的参数并根据这些参数更新套接字的状态或行为。
函数功能及作用 setsockopt 函数的主要功能是设置套接字的选项。这些选项可以影响套接字的行为、性能、安全性等方面。以下是一些常见的套接字选项及其作用
SO_REUSEADDR允许套接字在关闭后立即重新使用其地址。这对于服务器程序来说非常有用因为它们通常需要绑定到一个固定的端口上。 SO_KEEPALIVE启用 TCP 的保活机制。当连接空闲一段时间后TCP 会自动发送保活探测报文以检查连接是否仍然可用。 SO_RCVBUF 和 SO_SNDBUF分别设置套接字的接收和发送缓冲区大小。这可以影响套接字的吞吐量和延迟。 IP_TOS或 IPV6_TCLASS设置 IP 头部的类型服务Type-of-Service字段或流量类别Traffic Class字段。这可以用于 QoS服务质量配置。 TCP_NODELAY禁用 Nagle 算法。Nagle 算法是一种用于减少小数据包数量的技术但在某些场景下如实时通信可能会导致延迟。禁用 Nagle 算法可以减少延迟。 通过设置这些选项你可以根据需要定制套接字的行为以满足你的应用程序的特定需求。 TCP协议中主动断开连接的一方会有timewait状态到close这个状态变化由timewait状态到close的必要性在哪里能不能让它发送了ack后就直接close不经过timewait状态 在TCP协议中主动断开连接的一方在发送FIN报文并收到对方ACK报文后会进入TIME_WAIT状态而不是直接关闭CLOSE状态这个状态的存在有其必要性主要体现在以下几个方面
保证挥手成功 即 被动关闭方收到最后一个ack又继续发信息或者最后一个ack丢失被动关闭方重复发送fin保证主动关闭方能够收到让被动关闭方成功收到ack进入closed状态(如果由于最后一个ack丢失被动关闭方无法退出一直发fin过一段时间他也要退出的他不可能一直等待。)ack丢了服务端重发的fin也丢了怎么办同上过一段时间他也要退出的他不可能一直等待---- 提高四次挥手的容错性防止最后一个ack或历史网络报文与新连接的syn报文混淆 --通信双方历史数据消散【题外话序号是随机的防止黑客得出序号规律发恶意报文/ 历史数据影响新数据】
保证对端能收到ACK报文 TIME_WAIT状态的存在是为了确保在主动关闭方发送的最后一个ACK报文丢失的情况下被动关闭方能够重传FIN报文。这样主动关闭方可以再次进入TIME_WAIT状态并重传ACK报文从而确保连接的正确关闭。 防止已失效的报文段被后续连接接收 客户端发送最后一个ACK后再经过一个2MSL报文最大生存时间一个报文在网络中一来一回时间就可以使本连接持续时间内所产生的所有报文段都从网络中消失。从而确保在关闭连接后客户端发送的最后一个ACK报文段不会与新连接的SYN报文段混淆。这是TCP协议设计的一个精妙之处通过保证旧的连接状态在网络中“消失”的时间足够长来避免与新连接发生冲突。 确保被动关闭方关闭连接 在TIME_WAIT状态期间主动关闭方可以等待被动关闭方可能发送的FIN报文段。如果被动关闭方在收到主动关闭方的ACK后没有立即关闭连接而是在稍后的某个时间点发送FIN报文段那么主动关闭方可以正确地处理这个FIN报文段确保连接的完全关闭。 至于是否能让主动关闭方在发送了ACK后直接关闭不经过TIME_WAIT状态答案是不可以。这是因为TCP协议的设计考虑到了网络的不稳定性和报文丢失的可能性而TIME_WAIT状态的存在正是为了确保在这些情况下连接仍然能够正确地关闭。如果取消了TIME_WAIT状态可能会导致连接无法正常关闭甚至引发新的连接与旧的连接发生冲突的问题。
综上所述TIME_WAIT状态在TCP协议中是一个重要的状态它的存在确保了连接的正确关闭并避免了与新连接发生冲突的可能性。 MSL MSLMaximum Segment Lifetime在网络通信中特别是在TCP协议中指的是报文段最大生存时间。以下是关于MSL的详细描述
定义 MSL是TCP协议中定义的一个计时器值用于确定一个TCP报文段在网络中可以存在或传输的最长时间。 作用 如果在MSL时间内TCP报文段没有被接收方确认即没有收到ACK报文发送方会认为该报文段已经丢失并可能会重传该报文段。 在TCP的四次挥手过程中MSL对于确保连接的正确关闭和避免与新连接混淆具有重要意义。 应用场景 当主动关闭方通常是客户端发送完FIN报文段并进入TIME_WAIT状态时它会等待2MSL两倍的最大报文段生存时间的时间才进入CLOSED状态。这是为了确保被动关闭方通常是服务器发送的ACK报文段在网络中已经消失避免与新连接中可能出现的具有相同序列号的数据包发生混淆。 数值 MSL的具体值取决于网络环境和操作系统的实现。在大多数现代操作系统中MSL通常被设置为大约30秒到2分钟的时间但这个值可能会因网络条件和操作系统配置的不同而有所变化。 总结 MSL是TCP协议中用于确保报文段传输可靠性的一个关键参数。通过设定报文段在网络中的最大生存时间TCP协议能够在网络不稳定或报文丢失的情况下通过重传机制来保证数据传输的完整性和可靠性。同时在连接关闭的过程中MSL也起到了避免与新连接混淆的重要作用。 最大传送时间 在网络中发数据是很快的 最大传送时间一般是ms级别的
msl是指一个报文的存活时间 即如果一个报文阻塞在网络中 过了msl他也要死亡 msl一般多久 MSLMaximum Segment Lifetime通常指的是报文最大生存时间是任何报文在网络上存在的最长时间超过这个时间报文将被丢弃。以下是关于MSL时长的常见设置和规定
标准规定根据RFC 793或RFC 0793的旧版本MSL被规定为2分钟。 实际应用 在实际应用中MSL的时长可能会有所不同。常见的时长设置包括30秒、1分钟或2分钟。 Linux系统中net.ipv4.tcp_fin_timeout的数值记录了2MSL状态需要等待的超时时间以秒为单位。 可修改性在绝大多数的情况下MSL的值是可以根据需要进行修改的。 综上所述MSL的时长并非固定不变而是可以根据实际网络环境和需求进行调整。常见的MSL时长设置包括30秒、1分钟和2分钟。如需更详细的信息或特定网络环境下的MSL设置建议咨询网络管理员或参考相关网络设备的文档。