精华内容
下载资源
问答
  • 一个Linux TCP服务器程序的实现
    千次阅读
    2019-05-24 16:57:20

    一. 前言

            本文将介绍一个简单 Linux TCP 服务器程序的实现,功能是只要客户端发送连接请求过来,就发送"Hello World"给客户端。

    二. 基本概念

    套接字

            在 TCP/IP 协议中,"IP+端口" 可以唯一标识网络通讯中的一个进程。套接字(socket)本身有插座的意思,它是用于进程间网络通讯的一种特殊文件类型,这种文件跟普通文件不一样,普通文件需要存储在硬盘上,而 socket 文件是借助内核缓冲区形成的伪文件。在 Linux 读写普通文件时,我们先使用 open 函数打开文件然后获取文件句柄 fd,然后调用 read 函数就可以读取文件内容,调用 write 函数就可以往文件写入内容。socket 也可以类似理解为这样的文件描述符,可以理解为:如果网络通讯中两个进程要通讯就需要借助套接字(socket)来实现。

            假设现在服务器创建了一个 socket 并且处于监听状态,客户端也创建了一个 socket 与服务器建立起连接,然后客户端就可以通过 write 给服务器发送数据,通过 read 读取服务器发送来的数据。

    CS模型

            C/S 模型又称为客户端/服务器模型,对于 TCP 客户端/服务器模型开发一般如下图所示。

    三. Linux TCP服务器程序实现

      1 #include <sys/types.h>
      2 #include <sys/socket.h>
      3 #include <string.h>
      4 #include <netinet/in.h>
      5 #include <arpa/inet.h>
      6 #include <unistd.h>
      7 #include <stdio.h>
      8 
      9 #define SERVER_PORT 8080
     10 
     11 int main()
     12 {
     13     int listen_fd = socket(AF_INET,SOCK_STREAM,0);
     14     int conn_fd = 0;
     15     char data[] = "Hello World!";
     16 
     17     struct sockaddr_in server_addr;
     18     memset(&server_addr,0,sizeof(server_addr));
     19     server_addr.sin_family = AF_INET;
     20     server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
     21     server_addr.sin_port = htons(SERVER_PORT);
     22     
     23     bind(listen_fd,(struct sockaddr *)&server_addr,sizeof(server_addr));
     24     listen(listen_fd,32);
     25     
     26     while(1)
     27     {
     28         conn_fd = accept(listen_fd,(struct sockaddr *)NULL,NULL);
     29         write(conn_fd,data,strlen(data));
     30         close(conn_fd);
     31     }
     32     close(listen_fd);
     33
     34     return 0;
     35 }

    程序讲解

    1. 首先调用一个 socket 函数创建一个监听套接字,第一个参数 AF_INET 代表是 IPv4 地址,第二个参数 SOCK_STREAM 代表流式协议,第三个参数 0 代表默认协议,这里是 TCP。

    2. 将套接字与具体的 IP 和端口绑定,需要调用 bind 函数,bind 函数的第一个参数是需要绑定的 socket,第二个参数是一个 struct sockaddr 类型的指针,第三个参数是 struct sockaddr 类型的指针指向的数据长度。可以看到,创建了 struct sockaddr_in 结构体后,将其程序 sin_family 指定为 AF_INET,即 IPv4 类型;将 sin_addr.s_addr 指定为 INADDR_ANY 代表使用主机的任意一个地址(因为一个电脑可以有多个网卡,拥有多个 IP 地址);将 sin_port 指定为 8080,这样该套接字就与一个本地 IP 和 8080 端口绑定起来了。

    3.调用 listen 函数指定处于连接就绪队列的连接数最大值。

    4.在 while(1) 中 accept 阻塞等待客户端发送连接请求过来,一旦成功与客户端连接,accept 函数就返回一个与客户端通讯的通讯套接字(注意监听套接字与通讯套接字不同),然后往通讯套接字写入数据,再调用 close 关闭连接。

    关于上述一些 API 的具体含义将会在后续文章做深入讲解,这里只需要先简单了解含义即可。

    四. 功能调试

    编写完 server.c 文件后,需要编译产生可执行文件然后运行。

    编译:gcc server.c -o server

    运行:./server

    运行 server 程序后,需要有对应的客户端程序去发起访问,这里介绍一个好用的客户端工具:telnet。

    Ubuntu 下安装 telnet:sudo apt-get install telnet

    telnet 使用,在命令行模式下输入:telnet IP地址 端口,如 telnet 127.0.0.1 8080 就可以发起对本地 8080 端口的访问了。

    如上,使用 telnet 往 127.0.0.1 的 8080 端口建立连接后,客户端收到了 Hello,world!,这句话是服务器程序 write 函数调用的结果,然后显示 Connection closed by foreign ost,这是因为每次连接后服务器发送完 Hello,world! 就 close 掉这个 socket 了。

    更多相关内容
  • Linux内核中的TCP参数 /proc/sys/net/ipv4/ /proc/sys/net/ipv4/存放着TCP参数的文件,目录中的内容用来添加网络设置,在其中的许多设置,可以用来阻止对系统的攻击,或用来设置系统的路由功能。 tcp_syn_retries ...

    Linux内核中的TCP参数

    /proc/sys/net/ipv4/

    /proc/sys/net/ipv4/存放着TCP参数的文件,目录中的内容用来添加网络设置,在其中的许多设置,可以用来阻止对系统的攻击,或用来设置系统的路由功能。

    image-20210805105142810

    tcp_syn_retries 客户端发起SYN连接,如果超时会进行重传,重传的次数

    image-20210805110335709

    接着我们使用sysctl net.ipv4.tcp_syn_retries=2把这个参数修改为2测试一下

    image-20210805110812417

    接着我们来验证一下,我们去ssh一台不存在的主机,因为ssh也是基于tcp

    image-20210805110607314

    通过wireshark抓包可以看到,果然重传了2个数据包

    image-20210805111014541

    net.ipv4.tcp_window_scaling启用或关闭窗口扩大因子选项

    image-20210805112138088

    image-20210805112002926

    image-20210805112330211

    net.ipv4.tcp_sack启用或关闭选择确认(Selective Acknowledgement, SACK)选项

    image-20210805112042693

    名称默认值建议值描述
    tcpsyn_retries51对于一个新建连接,内核要发送多少个SYN连接请求才决定放弃。不应该大于255,默认值是5,对应于180毫秒左右时间。(对于大负载而物理通信良好的网络来说,这个值偏高,可以修改为2。这个值仅仅是针对对外的连接,对进来的连接,是由tcp_retries1决定)
    tcp_synack_retries51对于远端的连接请求SYN,内核会发送SYN+ACK数据包,以确认收到上一个SYN连接请求包。这是所谓的三次握手机制的第二个步骤。这里决定内核再放弃之前所发送出的SYN+ACK数目。不应该大于255,默认值是5,对应于180秒左右时间。
    tcp_keepalive_time7200600TCP发送keepalive探测消息的间隔时间(秒),用于确认TCP连接是否有效。防止两边建立连接但不发送数据的攻击。
    tcp_keepalive_probes93TCP发送keepalive探测消息的间隔时间(秒),用于确认TCP连接是否有效。
    tcp_keepalive_intvl7415探测消息未获得响应时,重发该消息的间隔时间(秒)。默认值为75秒。 (对于普通应用来说,这个值有一些偏大,可以根据需要改小.特别是web类服务器需要改小该值,15是个比较合适的值)
    tcp_retries133放弃回应一个TCP连接请求前﹐需要进行多少次重试。RFC 规定最低的数值是3
    tcp_retries2155在丢弃激活(已建立通讯状况)的TCP连接之前﹐需要进行多少次重试。默认值为15,根据RTO的值来决定,相当于13-30分钟(RFC1122规定,必须大于100秒) (这个值根据目前的网络设置,可以适当地改小,我的网络内修改为了5)
    tcp_orphan_retries73在近端丢弃TCP连接之前﹐要进行多少次重试。默认值是7个﹐相当于 50秒 - 16分钟﹐视 RTO 而定。如果您的系统是负载很大的web服务器﹐那么也许需要降低该值,这类 sockets 可能会耗费大量的资源。另外参的考tcp_max_orphans
    tcp_fin_timeout602对于本端断开的socket连接,TCP保持在FIN-WAIT-2状态的时间。对方可能会断开连接或一直不结束连接或不可预料的进程死亡。默认值为60
    tcp_max_tw_buckets18000036000系统在同时所处理的最大 timewait sockets 数目。如果超过此数的话,time-wait socket 会被立即砍除并且显示警告信息。之所以要设定这个限制﹐纯粹为了抵御那些简单的 DoS 攻击﹐不过﹐如果网络条件需要比默认值更多﹐则可以提高它(或许还要增加内存)。(事实上做NAT的时候最好可以适当地增加该值)
    tcp_tw_recycle01打开快速 TIME-WAIT sockets 回收。除非得到技术专家的建议或要求﹐请不要随意修改这个值。(做NAT的时候,建议打开它)
    tcp_tw_reuse01表示是否允许重新应用处于TIME-WAIT状态的socket用于新的TCP连接(这个对快速重启动某些服务,而启动后提示端口已经被使用的情形非常有帮助)
    tcp_max_orphans819232768系统所能处理不属于任何进程的TCP sockets最大数量。假如超过这个数量,那么不属于任何进程的连接会被立即reset,并同时显示警告信息。之所以要设定这个限制,纯粹为了抵御那些简单的 DoS攻击,千万不要依赖这个或是人为的降低这个限制。如果内存大更应该增加这个值。(这个值Redhat AS版本中设置为32768,但是很多防火墙修改的时候,建议该值修改为2000)
    tcp_abort_on_overflow00当守护进程太忙而不能接受新的连接,就象对方发送reset消息,默认值是false。这意味着当溢出的原因是因为一个偶然的猝发,那么连接将恢复状态。只有在你确信守护进程真的不能完成连接请求时才打开该选项,该选项会影响客户的使用。(对待已经满载的sendmail,apache这类服务的时候,这个可以很快让客户端终止连接,可以给予服务程序处理已有连接的缓冲机会,所以很多防火墙上推荐打开它)
    tcp_synookies01只有在内核编译时选择了CONFIG_SYNCOOKIES时才会发生作用。当出现syn等候队列出现溢出时象对方发送syncookies。目的是为了防止syn flood攻击。
    tcp_stdurg00使用 TCP urg pointer字段中的主机请求解释功能。大部份的主机都使用老旧的 BSD解释,因此如果您在 Linux 打开它,或会导致不能和它们正确沟通。
    tcp_max_syn_backlog102416384对于那些依然还未获得客户端确认的连接请求,需要保存在队列中最大数目。对于超过 128Mb 内存的系统,默认值是 1024 ,低于 128Mb 的则为 128。如果服务器经常出现过载,可以尝试增加这个数字。假如您将此值设为大于 1024,最好修改include/net/tcp.h里面的TCP_SYNQ_HSIZE,以保持TCP_SYNQ_HSIZE*16(SYN Flood攻击利用TCP协议散布握手的缺陷,伪造虚假源IP地址发送大量TCP-SYN半打开连接到目标系统,最终导致目标系统Socket队列资源耗尽而无法接受新的连接。为了应付这种攻击,现代Unix系统中普遍采用多连接队列处理的方式来缓冲(而不是解决)这种攻击,是用一个基本队列处理正常的完全连接应用(Connect()和Accept() ),是用另一个队列单独存放半打开连接。这种双队列处理方式和其他一些系统内核措施(例如Syn-Cookies/Caches)联合应用时,能够比较有效的缓解小规模的SYN Flood攻击(事实证明)
    tcp_window_scaling11该文件表示设置tcp/ip会话的滑动窗口大小是否可变。参数值为布尔值,为1时表示可变,为0时表示不可变。tcp/ip通常使用的窗口最大可达到65535字节,对于高速网络,该值可能太小,这时候如果启用了该功能,可以使tcp/ip滑动窗口大小增大数个数量级,从而提高数据传输的能力(RFC 1323)。
    tcp_timestamps11Timestamps 用在其它一些东西中,可以防范那些伪造的sequence号码。一条1G的宽带线路或许会重遇到带 out-of-line数值的旧sequence 号码(假如它是由于上次产生的)。Timestamp 会让它知道这是个 ‘旧封包’。(该文件表示是否启用以一种比超时重发更精确的方法(RFC 1323)来启用对RTT的计算;为了实现更好的性能应该启用这个选项。)
    tcp_sack11使用 Selective ACK,它可以用来查找特定的遗失的数据报— 因此有助于快速恢复状态。该文件表示是否启用有选择的应答(Selective Acknowledgment),这可以通过有选择地应答乱序接收到的报文来提高性能,这样可以让发送者只发送丢失的报文段。对于广域网通信来说这个选项应该启用,但是这会增加对 CPU 的占用。
    tcp_fack11打开FACK拥塞避免和快速重传功能。注意,当tcp_sack设置为0的时候,这个值即使设置为1也无效,这个是TCP连接靠谱的核心功能
    tcp_dsack11允许TCP发送”两个完全相同”的SACK
    tcp_ecn00TCP的直接拥塞通告功能。
    tcp_reordering36TCP流中重排序的数据报最大数量。 一般有看到推荐把这个数值略微调整大一些
    tcp_retans_collapse10对于某些有bug的打印机提供针对其bug的兼容性。一般不需要这个支持,可以关闭它
    tcp_wmem:mindefaultmax4096 16384 1310728192 131072 16777216发送缓存设置。 min:为TCP socket预留用于发送缓冲的内存最小值。每个tcp socket都可以在建议以后都可以使用它。默认值为4096(4K)。 default:为TCP socket预留用于发送缓冲的内存数量,默认情况下该值会影响其它协议使用的net.core.wmem_default 值,一般要低于net.core.wmem_default的值。默认值为16384(16K)max: 用于TCP socket发送缓冲的内存最大值。该值不会影响net.core.wmem_max,”静态”选择参数SO_SNDBUF则不受该值影响。默认值为131072(128K)。对于服务器而言,增加这个参数的值对于发送数据很有帮助
    tcprmem:mindefaultmax4096 87380 17476032768 131072 16777216接收缓存设置。同tcp_wmem
    tcp_mem:mindefaultmax根据内存计算786432 1048576 1572864low:当TCP使用了低于该值的内存页面数时,TCP不会考虑释放内存。即低于此值没有内存压力。(理想情况下,这个值应与指定给 tcp_wmem 的第 2 个值相匹配 - 这第 2 个值表明,最大页面大小乘以最大并发请求数除以页大小 (131072 300 / 4096)。 ) pressure:当TCP使用了超过该值的内存页面数量时,TCP试图稳定其内存使用,进入pressure模式,当内存消耗低于low值时则退出pressure状态。(理想情况下这个值应该是 TCP 可以使用的总缓冲区大小的最大值 (204800 300 / 4096)。 ) high:允许所有tcp sockets用于排队缓冲数据报的页面量。(如果超过这个值,TCP 连接将被拒绝,这就是为什么不要令其过于保守 (512000 *300 / 4096) 的原因了。 在这种情况下,提供的价值很大,它能处理很多连接,是所预期的 2.5 倍;或者使现有连接能够传输 2.5 倍的数据。
    tcp_app_win3131保留max(window/2^tcp_app_win, mss)数量的窗口由于应用缓冲。当为0时表示不需要缓冲。
    tcp_adv_win_scale22计算缓冲开销。
    tcp_low_latency00允许 TCP/IP 栈适应在高吞吐量情况下低延时的情况;这个选项一般情形是的禁用。
    tcp_westwood00启用发送者端的拥塞控制算法,它可以维护对吞吐量的评估,并试图对带宽的整体利用情况进行优化;对于 WAN 通信来说应该启用这个选项。
    tcp_bic00为快速长距离网络启用Binary Increase Congestion;这样可以更好地利用以 GB 速度进行操作的链接;对于 WAN 通信应该启用这个选项。
    ip_forward01NAT必须开启IP转发支持,把该值写1
    ip_local_port_range:minmax32768 610001024 65000表示用于向外连接的端口范围,默认比较小,这个范围同样会间接用于NAT表规模。
    ip_conntrack_max6553565535系统支持的最大ipv4连接数,默认65536(事实上这也是理论最大值),同时这个值和你的内存大小有关,1G以上内存这个值都是默认65536

    /proc/sys/net/core/

    /proc/sys/net/core/目录中包括许多设置用来控制Linux内核与网络层的交互,即当网络有什么动作时,内核做出什么样的相应反应。

    image-20210805105405147

    名称默认值建议值描述
    netdev_max_backlog102416384每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目,对重负载服务器而言,该值需要调高一点。
    somaxconn12816384用来限制监听队列最大数据包的数量,超过这个数量就会导致链接超时或者触发重传机制。web应用中listen函数的backlog默认会给我们内核参数的net.core.somaxconn限制到128,而nginx定义的NGX_LISTEN_BACKLOG默认为511,所以有必要调整这个值。对繁忙的服务器,增加该值有助于网络性能
    wmem_default129024129024默认的发送窗口大小(字节)
    rmem_default129024129024默认的接收窗口大小(字节)
    rmem_max129024873200最大的TCP数据接收缓冲(字节)
    wmem_max129024873200最大的TCP数据发送缓冲(字节)

    /proc/sys/net/netfilter/是对netfilter的参数配置,具体可以参照Linux内核文档

    image-20210805105314615

    修改内核参数的方法

    1. 使用 echo value 方式直接追加到文件中。 如 echo "1" > /proc/sys/net/ipv4/tcp_syn_retries ,但是这种方式设备重启后,会恢复成默认值。
    2. 把参数添加到 /etc/sysctl.conf 中,然后执行 sysctl -p 使参数生效。这种方式是永久有效的。
    3. 使用systcl命令进行修改,例如修改SYN重传次数sysctl net.ipv4.tcp_syn_retries=n

    查看Linux系统的统计信息

    image-20210805132032014

    下面的eth0换成需要查看的网卡

    sys/class/net/eth0/statistics/rx_packets 收到的数据包数量
    
    sys/class/net/eth0/statistics/tx_packets 传输的数据包数量
    
    sys/class/net/eth0/statistics/rx_bytes 接收的字节数
    
    sys/class/net/eth0/statistics/tx_bytes 传输的字节数
    
    sys/class/net/eth0/statistics/rx_dropped 收包时丢弃的数据包
    
    sys/class/net/eth0/statistics/tx_dropped 发包时丢弃的数据包
    

    Linux网卡的参数可以在/sys/class/net/进入对应网卡目录去查看,比如网卡的MAC地址速率(speed),MTU等等image-20210805132416709

    参考资料

    Linux TCP/IP调优-Linux内核参数注释

    Linux内核TCP/IP参数优化

    推荐阅读

    Linux运维一定要知道的服务管理!

    Linux运维一定要懂的sudoers!

    Linux配置RAID详解(全)!

    Linux黑客入侵检测的排查思路(全)

    展开全文
  • Linux-TCP

    2021-05-14 02:39:26
    image.png1. TIME_WAIT1.1 TIME_WAIT状态如何产生?由上面的变迁图,首先调用close()发起主动关闭的一方,在...产生这种结果使得这个TCP连接在2MSL连接等待期间,定义这个连接的四元组(客户端IP地址和端口,服务端IP...

    603412d2db49

    image.png

    1. TIME_WAIT

    1.1 TIME_WAIT状态如何产生?

    由上面的变迁图,首先调用close()发起主动关闭的一方,在发送最后一个ACK之后会进入time_wait的状态,也就说该发送方会保持2MSL时间之后才会回到初始状态。MSL值得是数据包在网络中的最大生存时间。产生这种结果使得这个TCP连接在2MSL连接等待期间,定义这个连接的四元组(客户端IP地址和端口,服务端IP地址和端口号)不能被使用。

    1.2 TIME_WAIT状态产生的原因

    为实现TCP全双工连接的可靠释放

    由TCP状态变迁图可知,假设发起主动关闭的一方(client)最后发送的ACK在网络中丢失,由于TCP协议的重传机制,执行被动关闭的一方(server)将会重发其FIN,在该FIN到达client之前,client必须维护这条连接状态,也就说这条TCP连接所对应的资源(client方的local_ip,local_port)不能被立即释放或重新分配,直到另一方重发的FIN达到之后,client重发ACK后,经过2MSL时间周期没有再收到另一方的FIN之后,该TCP连接才能恢复初始的CLOSED状态。如果主动关闭一方不维护这样一个TIME_WAIT状态,那么当被动关闭一方重发的FIN到达时,主动关闭一方的TCP传输层会用RST包响应对方,这会被对方认为是有错误发生,然而这事实上只是正常的关闭连接过程,并非异常。

    为使旧的数据包在网络因过期而消失

    为说明这个问题,我们先假设TCP协议中不存在TIME_WAIT状态的限制,再假设当前有一条TCP连接:(local_ip, local_port, remote_ip,remote_port),因某些原因,我们先关闭,接着很快以相同的四元组建立一条新连接。本文前面介绍过,TCP连接由四元组唯一标识,因此,在我们假设的情况中,TCP协议栈是无法区分前后两条TCP连接的不同的,在它看来,这根本就是同一条连接,中间先释放再建立的过程对其来说是“感知”不到的。这样就可能发生这样的情况:前一条TCP连接由local peer发送的数据到达remote peer后,会被该remot peer的TCP传输层当做当前TCP连接的正常数据接收并向上传递至应用层(而事实上,在我们假设的场景下,这些旧数据到达remote peer前,旧连接已断开且一条由相同四元组构成的新TCP连接已建立,因此,这些旧数据是不应该被向上传递至应用层的),从而引起数据错乱进而导致各种无法预知的诡异现象。作为一种可靠的传输协议,TCP必须在协议层面考虑并避免这种情况的发生,这正是TIME_WAIT状态存在的第2个原因。

    总结

    具体而言,local peer主动调用close后,此时的TCP连接进入TIME_WAIT状态,处于该状态下的TCP连接不能立即以同样的四元组建立新连接,即发起active close的那方占用的local port在TIME_WAIT期间不能再被重新分配。由于TIME_WAIT状态持续时间为2MSL,这样保证了旧TCP连接双工链路中的旧数据包均因过期(超过MSL)而消失,此后,就可以用相同的四元组建立一条新连接而不会发生前后两次连接数据错乱的情况。

    1.3 TIME_WAIT状态如何避免

    首先服务器可以设置SO_REUSEADDR套接字选项来通知内核,如果端口忙,但TCP连接位于TIME_WAIT状态时可以重用端口。在一个非常有用的场景就是,如果你的服务器程序停止后想立即重启,而新的套接字依旧希望使用同一端口,此时SO_REUSEADDR选项就可以避免TIME_WAIT状态。

    2. TCP参数

    2.1 TCP_NODELAYED

    默认情况下, TCP发送数据采用Nagle算法.。Nagle算法是解决小数据的频繁发送问题,比如1个字节的数据,在封包后会加上几十字节的首部,相当浪费资源。Nagle的做法是发送方发送的数据不会立即发出,而是先放在缓冲区,等待缓冲区达到一定的大小,或者是缓冲达到一定的时间后再一批发出。 发送完一批数据后, 会等待接收方对这批数据的回应,然后再发送下一批数据.。Negle算法适用于发送方需要发送大批量数据, 并且接收方会及时作出回应的场合, 这种算法通过减少传输数据的次数来提高通信效率。

    如果发送方持续地发送小批量的数据, 并且接收方不一定会立即发送响应数据, 那么Negle算法会使发送方运行很慢。对于GUI 程序, 如网络游戏程序(服务器需要实时跟踪客户端鼠标的移动), 这个问题尤其突出.。客户端鼠标位置改动的信息需要实时发送到服务器上,由于Negle算法采用缓冲, 大大减低了实时响应速度, 导致客户程序运行很慢。

    我们可以通过设置TCP_NODELAYED来禁用Negle算法。

    2.2 so_keepalive

    so_keepalive是TCP的心跳机制,保持连接检测对方主机是否崩溃,避免(服务器)永远阻塞于TCP连接的输入。设置该选项后,如果2小时内在此套接口的任一方向都没有数据交换,TCP就自动给对方 发一个保持存活探测分节(keepalive probe)。这是一个对方必须响应的TCP分节。它会导致以下三种情况:

    对方接收一切正常:以期望的ACK响应,2小时后,TCP将发出另一个探测分节。

    对方已崩溃且已重新启动:以RST响应。套接口的待处理错误被置为ECONNRESET,套接 口本身则被关闭。

    对方无任何响应:源自berkeley的TCP发送另外8个探测分节,相隔75秒一个,试图得到一个响应。在发出第一个探测分节11分钟15秒后若仍无响应就放弃。套接口的待处理错误被置为ETIMEOUT,套接口本身则被关闭。如ICMP错误是“host unreachable(主机不可达)”,说明对方主机并没有崩溃,但是不可达,这种情况下待处理错误被置为 EHOSTUNREACH。

    SO_KEEPALIVE有三个参数,其详细解释如下:

    tcp_keepalive_intvl,保活探测消息的发送频率。默认值为75s。发送频率tcp_keepalive_intvl乘以发送次数tcp_keepalive_probes,就得到了从开始探测直到放弃探测确定连接断开的时间,大约为11min。

    tcp_keepalive_probes,TCP发送保活探测消息以确定连接是否已断开的次数。默认值为9(次)。值得注意的是,只有设置了SO_KEEPALIVE套接口选项后才会发送保活探测消息。

    tcp_keepalive_time,在TCP保活打开的情况下,最后一次数据交换到TCP发送第一个保活探测消息的时间,即允许的持续空闲时间。默认值为7200s(2h)。

    2.3 backlog

    更详细的信息参见:https://www.jianshu.com/p/a81ec7a47959

    对于TCP连接,内核维护两个队列:

    1. 未完成连接的队列,此队列维护着那些已收到了客户端SYN分节信息,等待完成三路握手的连接,socket的状态是SYN_RCVD。

    2. 已完成的连接的队列,此队列包含了那些已经完成三路握手的连接,socket的状态是ESTABLISHED,但是等待accept。

    2.3.1 backlog

    也可

    backlog在linux2.2之后表示队列2(已经完成连接,等待accept调用)。

    backlog的值太小会导致在大量连接的时候不能处理,丢弃客户端发送的ack,此时如果客户端认为连接建立继续发送数据,就会出现满请求。backlog过大会导致连接积压,性能下降。

    调用listen监听的时候可以设置backlog的值,然backlog 并不是按照你调用listen的所设置的backlog大小,实际上取的是backlog和somaxconn的最小值。somaxconn的值定义在/proc/sys/net/core/somaxconn,默认是128,可以把这个值修改更大以满足高负载需求。

    2.3.2 syn_backlog

    syn_backlog指队列1(半连接SYN_RCVD阶段)。

    这个值在/proc/sys/net/ipv4/tcp_max_syn_backlog ,可以对其进行调整。但是一般情况下处于syn_rcvd阶段的不会太多,除非遇到SYN_FLOOD攻击。

    SYN FLOOD:

    SYN Flood利用的是TCP协议缺陷,发送大量伪造的TCP连接请求,从而使得被攻击方资源耗尽(CPU满负荷或内存不足)的攻击方式。在被攻击主机用netstat可以看见80端口存在大量的半连接状态(SYN_RECV),用tcpdump抓包可以看见大量伪造IP发来的SYN连接,S也不断回复SYN+ACK给对方,可惜对方并不存在(如果存在则S会收到RST这样就失去效果了),所以会超时重传。这个时候如果有正常客户A请求S的80端口,它的SYN包就被S丢弃了,因为半连接队列已经满了,达到攻击目的。

    2.4 MSS

    MTU:数据链路层所能传输数据(扣除了数据链路层的协议头等信息)大小。例如,以太网的MTU是1500。

    MSS:TCP 为每个 TCP 连接控制这个最大大小,称为最大段大小 (MSS)。对于直接连接的网络,TCP 计算 MSS 的方法是使用网络接口的 MTU 大小然后减去协议头得到 TCP 信息包中数据的大小。例如,MTU 为 1500 的以太网在减去 20 字节的 IPv4 头和 20 字节的 TCP 头后得到的MSS 为 1460

    2.4.1 MSS的协商

    2.4.1.1建立连接时协商

    TCP在三次握手建立连接过程中,会在SYN报文中使用MSS(Maximum Segment Size)选项功能,协商交互双方能够接收的最大段长MSS值。

    MSS是传输层TCP协议范畴内的概念,顾名思义,其标识TCP能够承载的最大的应用数据段长度,因此,MSS=MTU-20字节TCP报头-20字节IP报头,那么在以太网环境下,MSS值一般就是1500-20-20=1460字节。

    客户端与服务器端分别根据自己发包接口的MTU值计算出相应MSS值,并通过SYN报文告知对方,我们还是通过一个实际环境中捕获的数据报文来看一下MSS协商的过程:

    603412d2db49

    点击查看原图

    上图为客户端的SYN报文,在其TCP选项字段,我们可以看到其通告的MSS值为1460;我们在看看服务器端的SYN/ACK报文解码:

    603412d2db49

    点击查看原图

    上图为服务器端给客户端回应的SYN/ACK报文,查看其TCP选项字段,我们可以发现其通告的MSS值为1440。

    交互双方会以双方通告的MSS值中取最小值作为发送报文的最大段长。在此TCP连接后续的交互过程中,我们可以清楚的看到服务器端向客户端发送的报文中,TCP的最大段长度都是1440字节,如下图解码所示:

    603412d2db49

    点击查看原图

    中间路径上的MTU问题,端系统并不知道,因此需要一个告知的机制,这种机制一共有两种:

    在建立连接时中间路由器也参与协商,但是该协商过程只在建立连接时进行。

    路径MTU发现(PMTUD: Path MTU Discovery ),该机制利用了IP

    报文禁止分段和ICMP报文实现了在建立连接之后动态的调整MTU。缺点如下:

    因为一些网络会封掉ICMP,所以该机制也有其缺点。如果ICMP被封掉,IP报文又禁止分段,就会导致故障。

    值得一提的是PMTUD仅TCP支持,UDP并不支持PMTUD。

    2.4.1.1.1 建立连接时中间路由器也参与协商的过程

    由于PMTUD可能存在ICMP差错报文被过滤的情况,很多中间设备的接口支持adjust tcp mss设置功能,思科路由器一般是在接口模式下使用命令“ip tcp adjust-mss 1400 ”来做设置,其他的品牌产品的相关设置大家可在实际工作环境下自查相关品牌和产品的使用手册。

    这个功能主要是通过由中间设备修改经过其转发的TCP SYN报文中的MSS值,让中间设备参与进TCP 三次握手时SYN报文的MSS协商来避免分片。

    需要注意的是,该功能不像MTU值,只针对出接口,此功能一旦开启,其将针对该接口的收发双向有效。

    我做一个简化环境下的工作过程图示以便于大家理解其工作过程:

    2.4.1.2 路径MTU发现

    DF标志位的作用

    一旦DF位置一,将不允许中间设备对该报文进行分片,那么在遇到IP报文长度超过中间设备转发接口的MTU值时,该IP报文将会被中间设备丢弃。在丢弃之后,中间设备会向发送方发送ICMP差错报文。

    为了简单直观的展示这个交互的过程,我做了下面这个图示:

    603412d2db49

    点击查看原图

    我们可以看到其差错类型为3,代码为4,并且告知了下一跳的MTU值为1478。在ICMP差错报文里封装导致此差错的原始IP报文的报头(包含IP报头和四层报头)。

    一旦出现这种因DF位置一而引起丢包,如果客户端无法正常处理的话,将会导致业务应用出现异常,外在表现为页面无法打开、页面打开不全、某些大文件无法传输等等,这将严重影响业务的正常运行。

    实际上通过该方式可以动态的通知和协商MTU,这也是路径MTU发现的基本原理。

    MTU具体过程

    TCP的路径MTU发现按如下方式进行:在连接建立时, TCP使用输出接口或对端声明的MSS中的最小M T U作为起始的报文段大小。路径M T U发现不允许T C P超过对端声明的M S S。如果对端没有指定一个M S S,则默认为5 3 6。

    一旦选定了起始的报文段大小,在该连接上的所有被T C P发送的I P数据报都将被设置D F比特。如果某个中间路由器需要对一个设置了D F标志的数据报进行分片,它就丢弃这个数据报,并产生一个I C M P的“不能分片”差错。如果收到这个I C M P差错, T C P就减少段大小并进行重传。如果路由器产生的是一个较新的该类I C M P差错,则报文段大小被设置为下一跳的M T U减去I P和T C P的首部长度。如果是一个较旧的该类I C M P差错,则必须尝试下一个可能的最小M T U(见图2 - 5)。当由这个I C M P差错引起的重传发生时,拥塞窗口不需要变化,但要启动慢启动。由于路由可以动态变化,因此在最后一次减少路径M T U的一段时间以后,可以尝试使用一个较大的值(直到等于对端声明的M S S或输出接口M T U的最小值)。RFC 11 9 1推荐这个时间间隔为1 0分钟(Solaris 2.2使用一个3 0分钟的时间间隔)。在对非本地目的地,默认的M S S通常为5 3 6字节,路径M T U发现可以避免在通过M T U小于5 7 6(这非常罕见)的中间链路时进行分片。对于本地目的主机,也可以避免在中间链路(如以太网)的M T U小于端点网络(如令牌环网)的情况下进行分片。但为了能使路径M T U更加有用和充分利用M T U大于5 7 6的广域网,一个实现必须停止使用为非本地目的制定的5 3 6的M T U默认值。M S S的一个较好的选择是输出接口的M T U(当然要减去I P和T C P的首部大小)

    (大多数的实现都允许系统管理员改变这个默认的M S S值,一些操作系统针对非本地目的地址使用默认值)。

    TCP/IP协议卷1中:涉及B S D / 3 8 6和S V R 4的M S S为1 0 2 4,这是因为许多B S D的实现版本需要M S S为5 1 2的倍数。其他的系统,如SunOS 4.1.3、Solaris 2.2 和AIX 3.2.2,当双方都在一个本地以太网上时都规定M S S为1 4 6 0。[Mogul 1993] 的比较显示了在以太网上1 4 6 0的M S S在性能上比1 0 2 4的M S S更好。如果目的I P地址为“非本地的( n o n l o c a l )”,M S S通常的默认值为5 3 6。而区分地址是本地还是非本地是简单的,如果目的I P地址的网络号与子网号都和我们的相同,则是本地的;如果目的I P地址的网络号与我们的完全不同,则是非本地的;如果目的I P地址的网络号与我们的相同而子网号与我们的不同,则可能是本地的,也可能是非本地的。大多数T C P实现版都提供了一个配置选项(附录E和图E - 1),让系统管理员说明不同的子网是属于本地还是非本地。这个选项的设置将确定M S S可以选择尽可能的大(达到外出接口的M T U长度)或是默认值5 3 6。

    现在TCP实现上针对非本地目的地址不使用默认MTU 576,使用输出接口的MTU)

    支持路径发现机制的主机,发送的TCP报文都指定DF位置1.一旦防火墙过滤ICMP报文,路径MTU发现机制就废了。

    603412d2db49

    image.png

    2.5 RST

    四次握手不是关闭 TCP连接的唯一方法. 有时,如果主机需要尽快关闭连接(或连接超时,端口或主机不可达),RST (Reset)包将被发送. 注意在,由于RST包不是TCP连接中的必须部分, 可以只发送RST包(即不带ACK标记). 但在正常的TCP连接中RST包可以带ACK确认标记。

    如果收到RST信号,说明连接已经出现问题,此时不能走正常的四次握手关闭连接。

    下面以客户端收到服务端的RST信号举例:

    客户端收到RST信号,说明连接需要异常关闭,此时客户端再向socket写或读事件时会触发异常。

    对于Netty,收到RST,向该socket写时会触发异常。同时RST信号到达会触发OP_READ,HeadHandler在处理OP_READ时异常,然后fireExceptionCaught事件。

    2.6 PUSH

    和NODELAY是相近的

    展开全文
  • 239-Linux TCP协议和UDP协议

    千次阅读 2022-03-09 11:12:13
    1.TCP 协议提供的是:面向连接、可靠的、字节流服务。使用 TCP 协议通信的双方必须先建立连接,然后才能开始数据的读写。双方都必须为该连接分配必要的内核资源,以管理连接的状态和连接上数据的传输。TCP 连接是全...

    1.TCP 协议提供的是:面向连接、可靠的、字节流服务。使用 TCP 协议通信的双方必须先建立连接,然后才能开始数据的读写。双方都必须为该连接分配必要的内核资源,以管理连接的状态和连接上数据的传输。TCP 连接是全双工的,双方的数据可以通过一个连接进行读写。完成数据交换之后,通信双方都必须断开连接以释放系统资源。使用 tcpdump 可以抓包观察 TCP 连接的建立与关闭。该命令需要管理员权限,格式如下(假设两个测试用的主机 IP 地址为 192.168.43.214 和 192.168.43.160 )
    在这里插入图片描述
    2.三次握手发生在客户端执行 connect()的时候,该方法返回成功,则说明三次握手已经建立。三次握手示例图如下:
    在这里插入图片描述
    四次挥手发生在客户端或服务端执行 close()关闭连接的时候,示例图如下:
    在这里插入图片描述
    3.为什么是三次握手,可不可以是两次,为什么?

    答案:不能是两次
    ①防止已过期的报文突然到达服务器,因而产生错误和资源浪费
    ②三次握手才能让双方都确认自己和对方的发送和接收能力都正常
    ③确认对方的初始序列号并告知对方自己的初始序列号

    4.三次握手时可能出现什么攻击?

    ①SYN FLOOD攻击(SYN洪泛攻击)
    SYN-FLOOD是一种常见的Dos攻击,拒绝服务攻击。通过网络服务所在的端口发送大量伪造原地址的攻击报文,发送到服务端,造成服务端上的半开连接队列被占满,从而阻止其他用户进行访问。
    它的数据报特征是大量SYN包,并且缺少最后一步的ACK回复

    原理:攻击者首先伪造地址,对服务器发起SYN请求,服务器回应SYN+ACK,而真实的IP会认为我没有发送请求,不做回应,而服务端没有收到回应,服务器就不知道是否发送成功,默认情况下重试5次 syn_retries,这样的话,对于服务器内存和带宽有很大的消耗

    ②解决SYN FLOOD方法
    (1)无效连接监控
    不停监视半开连接和不活动连接,当半开连接数和不活动连接数到达一定值时候,就释放系统资源。伤敌1000,自损8000
    (2)延缓TCB方法
    SYN FLOOD的关键是利用了,SYN数据报一到,系统就分配TCB资源。
    那么我们有两种方法资源问题
    Syn cache
    这种技术在收到Syn时不急着分配TCB,而是先回应一个ACK报文,并在一个专用的HASH表中保存这种连接,直到收到正确的ACK,才分配TCB
    Syn Cookie
    用一种特殊的算法生成sequence number,算法考虑到对方的信息和己方信息,收到对方的ACK报文后,验证之后才决定是否生成TCB

    5.未连接队列
    在三次握手协议中,服务器维护一个未连接队列,该队列为每个客户端的SYN包(syn=j)开设一个条目,该条目表明服务器已收到SYN包,并向客户发出确认,正在等待客户的确认包。这些条目所标识的连接在服务器处于SYN_RECV状态,当服务器收到客户的确认包时,删除该条目,服务器进入 ESTABLISHED 状态

    6.SYN-ACK 重传
    服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传,如果重传次数超过系统规定 的最大重传次数,系统将该连接信息从半连接队列中删除。注意,每次重传等待的时间不一定相同

    7.半连接存活时间
    是指半连接队列的条目存活的最长时间,也即服务从收到SYN包到确认这个报文无效的最长时间,该时间值是所有重传请求包的最长等待时间总和。有时我们也称半连接存活时间为Timeout时间、SYN_RECV存活时间

    8.挥手时,可能受到什么样的攻击?

    9.TCP连接各种状态解析

    ①FIN_WAIT_1: FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别是: FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET即进入到FIN_WAIT_1状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2状态,当然在实际的正常情况下,无论对方何种情况下,都应该马上回应ACK报文,所以FIN_WAIT_1状态一般是比较难见到的,而FIN_WAIT_2状态还有时常常可以用netstat看到。(主动方)

    FIN_WAIT_2:上面已经详细解释了这种状态,实际上FIN_WAIT_2状态下的SOCKET,表示半连接,也即有一方要求close连接,但另外一方告诉对方,我暂时还有点数据需要传送给你(ACK信息),稍后再关闭连接。(主动方)

    TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。(主动方)

    CLOSING(比较少见): 这种状态比较特殊,实际情况中应该是很少见,属于一种比较罕见的例外状态。正常情况下,当你发送FIN报文后,按理来说是应该先收到(或同时收到)对方的 ACK报文,再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文。什么情况下会出现此种情况呢?其实细想一下,也不难得出结论:那就是如果双方几乎在同时close一个SOCKET的话,那么就出现了双方同时发送FIN报文的情况,也即会出现CLOSING状态,表示双方都正在关闭SOCKET连接。

    CLOSE_WAIT: 这种状态的含义其实是表示在等待关闭。怎么理解呢?当对方close一个SOCKET后发送FIN报文给自己,你系统毫无疑问地会回应一个ACK报文给对方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正需要考虑的事情是查看你是否还有数据发送给对方,如果没有的话,那么你也就可以close这个SOCKET,发送FIN报文给对方,也即关闭连接。所以你在CLOSE_WAIT状态下,需要完成的事情是等待你去关闭连接。(被动方)

    LAST_ACK: 这个状态还是比较容易好理解的,它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到CLOSED可用状态了。(被动方)

    CLOSED: 表示连接中断

    10.默认情况下(不改变socket选项),当你调用close( or closesocket)时,如果发送缓冲中还有数据,TCP会继续把数据发送完

    11.发送了FIN只是表示本端不会继续发送数据了(应用层不会再调用send发送),但是对端还可以接收数据

    12.应用层如何知道对端关闭?通常,在最简单的阻塞模型中,当你调用recv时,如果返回0,则表示对端关闭。在这个时候通常的做法就是也调用close,那么TCP层就发送FIN,继续完成四次握手。如果你不调用close,那么对端就会处于FIN_WAIT_2状态,而本端则会处于CLOSE_WAIT状态

    13.在很多时候,TCP连接的断开都会由TCP层自动进行,例如你CTRL+C终止你的程序,TCP连接依然会正常关闭

    14.TCP 状态转移图
    TCP 连接的任意一端在任一时刻都处于某种状态,当前状态可以通过 nett stat 命令查看,下图是 TCP 连接从建立到关闭整个过程中通信两端状态的变化。其中 CLOSED 是假想的起始点,并不是一个实际的状态
    在这里插入图片描述
    上图中,TIME_WAIT 状态一般情况下是主动关闭的一端才会出现的状态。该状态出现后,会维持一段长为 2MSL(Maximum Segment Life)的时间,才能完全关闭。MSL 是 TCP 报文段在网络中的最大生存时间,标准文档 RFC1122 的建议值是 2min

    15.TIME_WAIT 状态存在的原因有两点
    ①可靠的终止 TCP 连接
    ②保证让迟来的 TCP 报文有足够的时间被识别并被丢弃

    在 Linux 系统上,一个 TCP 端口不能被同时打开多次(两次及以上)。当一个 TCP 连接处于 TIME_WAIT 状态时,我们将无法立即使用该连接占用着的端口来建立一个新连接。如果确实需要强制进程立即使用处于 TIME_WAIT 状态的连接所占用的端口,可以通过 setsockopt() 方法设置 socket 选项 SO_REUSEADDR 来完成

    16.复位报文段
    在某些特殊条件下,TCP 连接的一端会向另一端发送携带 RST 标志的报文段,即复位报文段,已通知对方关闭连接或重新建立连接。这里介绍一下三种情况:
    1)当客户端程序访问一个不存在的端口时,目标主机给它发送一个复位报文段
    2)异常终止连接。正常情况下,数据交换完成之后,一方给另一方发送 FIN 结束报文段。TCP 提供了异常终止一个连接的方法,即给对方发送一个复位报文段。一但发送了复位报文段,发送端所有排队等待发送的数据都将被丢弃。应用程序可以使用 socket 选项SO_LINGER 来设置发送复位报文段,以异常终止连接
    3) 处理半打开连接。例如 TCP 一端关闭了连接,由于网络故障对方没有收到结束报文,对方误以为连接仍然正常。处于这种状态的连接称为半打开连接。此时如果对端向连接写入数据,则会收到本端回复的复位报文段

    17.交互数据流与成块数据流
    TCP 按照携带应用程序数据长度可以分为两种:交互数据和成块数据。交互数据仅包含很少的字节。使用交互数据的应用程序对实时性要求极高,比如 telnet、ssh 等成块数据的长度则通过为 TCP 报文段允许的最大数据长度。使用成块数据的应用程序对传输效率要求高,比如 FTP

    18.带外数据
    有些传输层协议具有带外(out of Band,OOB)数据的概念,用于迅速通告对方本端发生的重要事件。因此,带外数据比普通数据有更高的优先级,它应该总是立即被发送,而不论发送缓冲区中是否有排队等待发送的普通数据

    UDP 没有实现带外数据传输,TCP 也没有真正的带外数据。不过 TCP 利用其头部中的紧急指针标志和紧急指针两个字段,给应用程序提供了一种传输紧急数据的方式,一般只有一个字节数据

    19.流式服务特点

    TCP 字节流的特点,发送端执行的写操作次数和接收端执行的读操作次数之间没有任何数量关系,应用程序对数据的发送和接收是没有边界限制的。如下图:
    在这里插入图片描述
    20.应答确认与超时重传

    TCP 发送的报文段是交给 IP 层传送的。但 IP 层只能提供尽最大努力的服务,也就是说,TCP 下面的网络所提供的是不可靠的传输。因此,TCP 必须采用适当的措施才能使两个运输层之间的通信变得可靠。TCP 的可靠传输是通过使用应答确认和超时重传来完成的

    下图是通过 netstat 命令抓包看到的信息
    在这里插入图片描述
    下图是无差错时,数据交互的流程:发送端发送数据 m1 给接收端,接收端收到数据后会给发送端一个确认信息,以表明数据已经被成功收到。在发送方未收到确认信息前,M1应继续被保留,直到确认信息到达才能丢弃
    在这里插入图片描述
    下图是出现差错时,数据交互的流程:
    在这里插入图片描述
    21.滑动窗口

    TCP 协议是利用滑动窗口实现流量控制的。一般来说,我们总是希望数据传输得更快一些,不会一次只发一个字节。但是如果发送方把数据发得过快,接受方就可能来不及接收,这就会造成数据的丢失。所谓流量控制就是让发送方的发送速率不要太快,要让接收方来的及接收

    在 TCP 的报头中有一个字段叫做接收通告窗口,这个字段由接收端填充,是接收端告诉发送端自己还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。所以发送端就会有一个发送窗口,这个发送窗口的大小是由接收端填充的接收通告窗口的大小决定的,并且窗口的位置会随着发送端数据的发送和接收到接收端对数据的确认而不断的向右滑动,将之称为滑动窗口

    发送方的滑动窗口示意图如下:
    在这里插入图片描述
    当收到 36 的 ack,并发出 46-51 的字节后,窗口滑动的示意图如下:
    在这里插入图片描述
    22.拥塞控制
    在计算机网络中的链路容量(即带宽)、交换结点中的缓存和处理机等,都是网络的资源。在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。这种情况就叫做拥塞。所谓拥塞控制就是防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载。拥塞控制是一个全局性的过程,涉及到所有主机,所有路由器,以及与降低网络传输性能有关的所有因素

    几种拥塞控制的方法:
    ①慢开始
    ②拥塞避免
    ③快速重传
    ④快速恢复

    慢开始、拥塞避免、快速恢复示意图:
    在这里插入图片描述
    快速重传示意图:
    在这里插入图片描述
    23.UDP 协议特点

    UDP 数据报服务特点:发送端应用程序每执行一次写操作,UDP 模块就将其封装成一个 UDP 数据报发送。接收端必须及时针对每一个 UDP 数据报执行读操作,否则就会丢包。并且,如果用户没有指定足够的应用程序缓冲区来读取 UDP 数据,则 UDP 数据将被截断
    在这里插入图片描述

    展开全文
  • Linux作为一个强大的操作系统,提供了一系列内核参数供我们进行调优。光TCP的调优参数就有50多个。在和线上问题斗智斗勇的过程中,笔者积累了一些在内网环境应该进行调优的参数。在此分享出来,希望对大家有所帮助。...
  • 全面了解linux TCP/IP协议栈

    万次阅读 多人点赞 2017-09-03 19:17:03
    简要说明 自从熟悉了linux socket编程(主要做posix socket的TCP/IP)之后,就一直以来就想写一篇对TCP/IP有一个比较全面的涵盖用户空间、内核以及网卡的文章,以便帮助大家在遇到基于socket的TCP/IP问题或困惑时能...
  • Linux TCP吞吐性能缺陷

    千次阅读 2022-01-14 07:50:18
    Linux内核协议栈实现的TCP(简称Linux TCP)是实际部署最多的TCP实现,遗憾的是,抛开协议本身的缺陷,Linux TCP还有自身实现的缺陷,实现层面的缺陷更直观可见。 至于其它家操作系统的协议栈实现,我没有亲见,不便...
  • Linux Tcp客户端和服务器端代码实现

    千次阅读 2015-07-30 23:59:22
    1、int socket(int domain, int type, int protocol);函数解析功能:创建socket,也就是创建一个socket... type: 服务类型,主要有SOCK_STREAM流服务(TCP协议使用),SOCK_DGRAM数据报服务(UDP协议使用)  protoc
  • 下面是写linuxtcp转发编程时,遇到的几个知识点,记录如下: (使用c/c++编程) 1. fork:创建子进程通信 服务端接受到请求后,fork出子进程,然后使用子进程与client通信
  • Linux 建立 TCP 连接的超时时间分析

    万次阅读 2018-01-28 20:22:27
    Linux 建立 TCP 连接的超时时间分析 Linux 建立 TCP 连接的超时时间分析 概述 超时分析 超时验证 如何改进 概述 Linux 系统默认的建立 TCP 连接的超时时间为 127 秒,对于许多客户端来说,这个时间都...
  • main ESTABLISHED keepalive (678.75/0/0) tcp6 0 0 10.9.66.112:22724 10.9.62.84:commplex-main ESTABLISHED keepalive (1014.62/0/0) tcp6 0 0 10.9.66.112:16519 10.9.62.137:commplex-main ESTABLISHED ...
  • tcp 超时与重传

    2021-05-18 08:16:14
    超时与重传最近没事,好好看下TCP 超时与重传,主要是参考TCP 卷1 2 ,TCP 如今在linux 2.6上实现许多细节变化较多,但基本机制或者说思路没有变化,变化的一些具体的算法上,更能适应今天的的高速网络,比如新的...
  • 前面的文章中,我稍微描述了一下如何隐藏一个TCP连接: https://blog.csdn.net/dog250/article/details/105372214 在上文中,我采用了 传统 的做法,即hook住proc的/proc/net/tcp展示接口,但这个方法并没有可观赏性...
  • TCP概述02. TCP特点03. TCP中CS架构04. TCP相关函数05. TCP服务端示例06. TCP客户端示例07. 附录 01. TCP概述 传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层...
  • TCP 异常断开

    2021-05-19 01:08:35
    但是如果业务有一点慢,比如数据库操作一次需要0.05秒,假设8万设备每秒产生5000个操作数据库的请求,那么设备每秒产生的请求需要服务端耗时25秒才能处理完(多进程的情况下可以缓解),这样请求不断累积会出现业务...
  • 描述卡内基梅隆大学的 CERT/CC 发出警告,称 Linux 内核 4.9 及更高版本中有一个 TCP 漏洞,该漏洞可使攻击者通过极小流量对系统发动 DoS (Denial-of-Service,拒绝服务)攻击。该漏洞是由诺基亚贝尔实验室支持的芬兰...
  • linux系统中,有很多种方式可以判断连接的对方网络是否已经断开。 通过错误码和信号判断 通过select系统函数判断 通过TCP_INFO套接字选项判断 通过SO_KEEPALIVE套接字选项判断 通过SO_RCVTIMEO/SO_SNDTIMEO...
  • TCP/IP在Linux下编程实现

    千次阅读 多人点赞 2019-05-14 20:49:19
    1.4 基于Windows平台的网络初始化和注销(Linux平台无需该操作) 二、套接字类型与协议设置 2.1 套接字函数socket(以Linux系统为例) 2.2 协议簇 2.3 数据传输类型 2.4 协议类型 三、地址簇与数据序列 3.1 ...
  • 本文后续部分将通过分析TCP/IP在Linux下的实现,来解释一下TCP的延迟确认机制。 1.为什么TCP延迟确认会导致延迟? 其实仅有延迟确认机制,是不会导致请求延迟的(初以为是必须等到ACK包发出去,recv系统调用才会返回)...
  • 另外家需要注意的是,很多对于 ip 的内核参数设置也会对 tcp 的行为产生影响.具体请参考linux 对于 ip 参数的帮助手册. 参数通常使用一个整形值来代表布尔型,设置为 0 时通常表示 "false",对应的一个非零值则表示 (...
  • Linux TCP/IP 协议栈调优

    千次阅读 2014-12-04 16:00:11
    有些性能瓶颈和LinuxTCP/IP的协议栈的设置有关,所以特别google了一下Linux TCP/IP的协议栈的参数意义和配置,记录一下。 如果想永久的保存参数的设置, 可以将参数加入到/etc/sysctl.conf中。如果想临时的更改...
  • 1.2 基于Linux的文件操作 1.2.1 底层文件访问和文件描述符 1.2.2 打开文件 1.2.3 关闭文件 1.2.4 将数据写入文件 1.2.5 读取文件中的数据 第二章 套接字类型与协议设置 2.1 套接字协议及其数据传输特性 ...
  • 1. 准备环境1.1 准备linux系统要求的linux系统可以是运行在物理机上,也可以...要求linux系统的内核版本为linux-4.1之后的版本,早期版本不支持NVMe over TCP;作者实验时用的是linux-5.0.7版本。为host主机端准备NQ...
  • TCP建立,释放连接

    2021-05-15 22:41:04
    TCP(Transmission Control Protocol) 传输控制协议TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接:位码即tcp标志位,有6种标示:SYN(synchronous建立联机)ACK(acknowledgement ...
  • 一 基于TCP的半关闭 TCP中的断开连接过程比建立连接过程更重要,因为连接过程中一般不会出现大... 参考 《TCP-IP网络编程(尹圣雨)》第7章 - 优雅地断开套接字连接 《TCP/IP网络编程》课后练习答案第一部分6~10章 尹圣雨
  • 原文:http://www.zhaoxiaodan.com/lnmp/%E6%89%93%E5%BC%80linux-tcp%E7%AB%AF%E5%8F%A3%E5%BF%AB%E9%80%9F%E5%9B%9E%E6%94%B6.html ---------------------------------------------------------------------------...
  • linux TCP流量控制

    千次阅读 2013-05-28 10:48:27
    I.流量控制 TCP使用流量控制来管理数据流量。流量控制限制发送字节大小,防止接收方接收缓存溢出。  1....这种情况会使接收方缓存...所以流量控制可以避免因接收方缓存溢出而产生的数据包丢弃,引起不必要的重传 TCP
  • 1. time_wait状态产生条件 只有在正常四次挥手关闭连接的情况下,在主动关闭连接的一方会出现一段时间的time_wait。如果启用了快速回收功能,回收时间和网络延迟状况有关,正常情况下小于1s,如果没有开启time_wait...
  • 用netstat -na命令发现系统中有大量状态为TIME-WAIT的TCP连接,google了下;修改了/etc/sysctl.conf中一些内核参数;解决了TCP连接中TIME-WAIT sockets的问题。编辑/etc/sysctl.conf文件,增加如下内容:#vi /etc/...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 105,447
精华内容 42,178
关键字:

linuxtcp6如何产生的