现在的位置: 首页 > 综合 > 正文

Linux高性能服务器编程(笔记1)

2013年10月07日 ⁄ 综合 ⁄ 共 9200字 ⁄ 字号 评论关闭

    自底向上:数据链路层,网络层,传输层,应用层
    数据链路层:实现了网卡结构的网络驱动程序,以处理数据在物理媒介上的传输。RAP(网络层将目标机器IP地址转换成物理地址才能使用数据链路层的服务)和RARP实现了IP地址和物理地址的转换。
    网络层:实现数据包的选路和转发,选择网络中的中间节点。IP(根据数据包的IP地址逐跳投递)和ICMP(主要用于网络检测连接,差错报文主要用来回应网络错误,查询报文用来查询网络信息如ping程序直接使用ICMP;ICMP使用同层的IP协议为其提供服务)
     传输层:为两台主机的应用程序提供端到端的通信,负责数据的收发链路的超时重传等,主要协议:TCP(可靠的(超时重传数据确认等方式),面向连接(先建立连接,内核维持必要的数据结构如缓存,结束断开连接),基于流(数据没有边界));UDP(不可靠(简单的向应用程序报错发送失败),无连接(通信双方不保持一个长久的联系),基于数据报(每个数据报都有自己的指定长度));SCTP为在因特网上传输电话信号而设计
     应用层:处理应用程序的逻辑,多数情形在内核空间实现。协议有多:ping是程序不是协议主要用于调试网络;telnet远程登陆协议;OSPF(open shortest path first开放最短路径优先)主要用于动态路由更新在路由器间通信以告知对方各自的路由信息
    上层协议采用封装的方式使用下层协议提供的服务,到达目的主机后沿着协议栈自底向上一次传递为分用(靠头部信息中的类型字段实现,如帧头部区分IP、RAP协议,IP数据报区分UDP、TCP、ICMP类型)。封装的数据形式:TCP报文段(内核缓存),UDP数据报,IP数据报,数据链路层为帧(以太网帧,令牌环帧)。帧的最大长度MTU(max transit unit)表示帧最多能携带多少上上层协议数据,以太网帧MTU(使用ifconfig和netstat可以查看)是1500字节,这里致使数据报可能分片的原因
     ARP:能实现任意网络层地址到任意物理地址的转换,工作原理:主机向自己所在的网络广播ARP报文,但是只有被请求解析的主机才回应ARP应答(其中有物理地址)。ARP报文长度28kb加上以太网帧18kb总共46kb,若实现要求以太网帧至少46kb则填充字节至64kb。ARP维护一个高速缓存其中包含经常访问或最近访问的机器的IP到物理地址的映射(避免了重复的ARP请求)。linux下用arp命令可以查看和修改(-d删除-s添加)ARP高速缓存
     DNS:域名查询服务,DNS是一套分布式的域名服务器,每个服务器山都存放着大量的机器名和IP地址的映射并且都是动态更新的
     ARP报文和DNS报文:
     IP协议为上层提供无状态(所有IP数据报相互独立,通信双方不同步传输数据的状态信息,只管将数据交给上层HTTP正需要这样的两次请求没有关联的无状态逻辑)、无连接(通信双方不长久的维持对方的任何信息因此每次发送数据都要指定地址)、不可靠的服务(尽最大努力交付,网络中有丢弃IP数据报的情况则向发送端回复ICMP错误消息,发送端只向上层报告发送失败)
    IPv4头部结构:
        4位版本号:IPv4是4
        4位头部长度:头部有多少32b,故IP头部长度最大15×32bB
        8位服务类型:3位优先权(已忽略);4位TOS字段分别可以表示:最小延时|最大吞吐量|最高可靠性|最小费用,其中只有一个可以置为1应用程序将根据实际需要设置它,如ssh和telnet是最小延时,ftp是最大吞吐量;1位保留字段必须为0
        16位总长度:以字节位单位,故IP数据报最大长度为2^16-1=65535B,但由于MTU限制可能被分片
        16位标识:唯一标识主机发送的每一个数据报,初始值系统随机生成其后每次加1,分片的数据报中所以分片的该值相同(分片复制)
         3位标志字段:第一位保留;第二位为禁止分片DF(若设置则表示不能分片若数据报超过MTU则被丢弃返回ICMP差错报文);第三位是更多分片MF,除最一个分片外其它分片都设置该位为1
        13位分片位移:分片相对于原始数据报开始处的偏移,实际的偏移值是该值左移三位即乘8,所以除最后一个分片外每个分片数据部分的长度必须是8的整数倍
         8位生存时间:到达目的地之前允许经过的路由器跳数,常为64,没经过一个路由值减1,当减为0时路由器丢弃数据报并向源端发送一个ICMP差错报文,该值可以防止数据报陷入路由循环
         8位协议:区分上层协议,ICMP是1,TCP是6,UDP是17
        16位头部校验和:接收端使用CRC算法校验IP头部
        32位源端IP地址和32位接收端IP地址:数据报传送过程中保持不变,帧头部的物理地址却在转发过程中一直变化
        选项字段:最多40字节(IP头部最大60字节-固定头部20字节),选项包括:记录路由,时间戳,松散源路由选择(指定一个路由IP地址列表数据发送必须经过其中所有的路由器,但是可以经过其它的路由器),严格源路由选择(数据报文只能经过所有指定的路由器)。路由选择大概只有traceroute程序使用,但是traceroute可以使用UDP和ICMP报文实现可靠的记录路由功能作为替代品。
     tcpdump抓包命令,未记录以太网帧尾部4kb的CRC字段,后接port domain表示只抓取使用域名服务的数据报即DNS查询和应答报文,host -t A www.google.com域名查询命令-t指明DNS协议使用哪种查询类型,不适用-t选项保留时间戳t cpdump抓IP数据报:tcpdump -ntx -i lo其中x选项使输出的数据包为二进制码,返回有IP地址端口号,tcpdump返回的IP数据报中Flags为s表示SYN同步报文段R表示复位报文段
    IP分片:IP数据报长度超过MTU时则分片,分片可能发生在发送端也可能在中转路由器上且可能在中途多次分片但是只有接收端重组。三个字段:数据报标示符id、标志MF、片偏移。IP数据报头部20B故其数据部分最长1480B。IP模块重组ICMP报文的时候只需要一份头部信息故只有第一个分片有ICMP头部,另外ICMP头部长度取决与报文的类型且变化范围大(ping是8B)。sudo tcpdump -ntv -i eht0 icmp(只抓取ICMP报文),ping 127.0.0.2 -s 1473向指定主机发送数据包
route//netstat -r查看路由表
    路由机制(匹配路由表中的哪一项):1)查找路由表中和数据报的目标IP地址完全匹配的主机IP地址 2)查找路由表中和数据表的目的IP地址具有相同网络ID的网络IP地址 3)选择默认路由通常下一跳路由是网关
路由更新:1)route add/del(静态路由更新);ICMP重定向报文也能更新路由表
    ICMP重定向报文:类型值为5,主机重定向代码值为1,给接收方提供了两个信息:引起ICMP重定向的IP数据报的源端IP地址(即哪个主机发送的报文可能具有更优路由),应该使用的路由IP地址。一般主机只接收ICMP报文,路由器只能发送ICMP报文。可以修改/etc/sys/net/ipv4/conf/all/send_redirects或者accept_redirects内核参数调整发送或接收选项。通常主机受到ICMP重定向报文是更新路由表缓冲而不是直接修改路由表route -Cn可以查看路由表缓冲。
    IP模块接收数据报首先CRC校验后分析头部信息。若头部设置了源站选路则转发模块处理该数据报,若数据报是发送给本主机的则根据协议字段交给上层,若不是发送给本主机的则调用转发子模块处理(首先要检验系统是否允许转发不允许则丢弃包,路由器具备转发功能,一般主机则只发送和接收/etc/sys/net/ipv4/ip_forward可以查看或修改)。转发子模块操作:1)检查TTL值是否为0是则丢弃 2)查看头部是否是源站选路,若是查看本机IP是否是某个目标IP不是则发送ICMP源站选路失败报文给发送端 3)若有必要则发送一个ICMP重定向报文给源端告诉它一个更合理的下一跳路由
4)TTL减1 5)处理IP头部 6)若有必要IP分片
    IPv6:解决了ipv4地址不够用,增加了多播和流解决多媒体内容质量的精细控制,引入自动配置功能使得局域网管理更加方便,增加了专门的网络安全功能。40B的固定头部和可变长的扩展头部
        4位版本号:6
        8位通信类型:指示数据流通信类型或优先级,与ipv4的TOS类似
        20位流标签:用于某些对连接的服务质量又特殊要求的通信如银屏或视屏的实时传输
        16位净和长度:指定IPv6扩展头部和应用程序数据长度之和,不包括固定头部
        8位下一包头:指定固定头部后的包头类型如扩展头、TCP等
        8位跳数限制:与TTL类似
        128位源端IP地址和128位目的端IP地址
        可变长的扩展头部长度为0表示没有扩展头部,一个数据报可以有多个扩展头部每个扩展头部的类型都是由前一个头部中的下一个报头字段指定
    IPv4地址采用十分点进制表示,IPv6地址用十六进制字符串表示,故IPv6地址分为8组每组2B。零压缩法:多个连续全零的组可以省略位::但是一个IPv6地址只能使用一次否则无法还原地址。
    IPv4数据报的以太网帧封装类型是0x800,IPv6数据报的以太网帧封装类型值是0x86dd
    TCP协议四个主要方面:TCP头部信息用于指定端口号管理TCP连接控制数据流(全双工);TCP状态转移过程(TCP连接的任意一端都是状态机);TCP数据流(交互数据流和成块数据流);TCP数据流控制(超时控制和拥塞控制)
    TCP服务特点:面向连接的可靠字节流传输。必须先建立连接内核分配内核资源最后断开连接释放资源。一对一的全双工连接,UDP无连接适合多播和广播。由于TCP拥有内核缓冲区故发送端和接收端每次读写都与缓冲区交互,所以TCP报文段个数与应用程序没有直接关系,这样体现了字节流的应用程序对数据的发送和接收是没有边界限制的概念。UDP没有内核缓冲区故每次应用程序写操作UDP模块都要将其封装成一个UDP数据报发送,接收端必须及时针对每一个UDP数据报执行读操作否则会丢包,如果用户没有指定足够的应用程序缓冲区则UDP数据报会被截断。UDP数据报在IP层不会分成多分UDP数据报进行传输(但是当UDP数据报长度加IP部首大于了MTU,会导致IP分片,就是将UDP数据报形成的IP数据报进行分片,每片的大小小于MTU,然后到下一站目的地就将每片的IP数据报重组,形成原来的UDP数据报形成的IP数据报)。TCP采用发送应答机制即每个TCP报文段都必须得到接收方的应答,采用超时重传机制即每次TCP报文段发送之后启动定时器如果在指定时间内没有收到应答则重发该报文段,由于IP数据报无序则TCP需要重组,UDP则交给上层协议处理数据确认和超时重传。TCP通过数据分段中的序列号来保证所有传输的数据可以按照正常的顺序进行重组
    TCP固定头部:
         16位源端口号和16位目的端口号:通常客户端使用系统自动选择的临时端口号服务器使用知名服务端口号(/etc/services)
         32位序号:同一传输方向上字节流的每个字节的编号,初始为随机值后序报文段是该报文数据第一个字节在数据流中的偏移tcpdump的-s选项可以打印序号绝对值
         32位确认号:ack收到的TCP序号值加1
         4位头部长度:单位4B,所以TCP最大长度为60B
         6位标志位:
               URG:紧急指针是否有效
               ACK:确认号是否有效,确认报文段
               PSH:接收端应用程序是否立即从TCP缓冲区读走数据
               RST:重新建立连接,复位报文段
               SYN:请求建立一个连接,同步报文段
               FIN:关闭连接,结束报文段
        16位窗口大小:接收通告窗口,告诉对方本端还有多大接收缓冲区用于控制数据流
        16位检验和:CRC校验
        16位应急指针:正的偏移量,它和序号字段值相加表示最后一个紧急数据的下一个字节的序号
        可变长的可选信息:最后40B(60B最大TCP长度-20B固定头部)
        kind选项:1B产生8个值
               0:结束选项
               1:空操作选项,没有特殊含义,一般用作TCP选项的填充
               2:最大报文段长度选项,连接初始化时双方使用该选项协商最大报文段长度MSS(max segment size),TCP模块将MSS值设置位MTU-40(TCP头部20B和IP头部20B),对于以太网而言MSS值位1460(1500-40)
               3:窗口扩大因子选项,连接初始化时双方使用该选项协商接收通信窗口的扩大因子。接收窗口是16位最大65535B但实际上TCP模块采用窗口扩大因子可以使窗口N提高到N×2^M即左移因子M位,窗口扩大因子只能出现在同步报文(SYN)中否则会被忽略,因为连接固定好后因子就不变了
               4:SACK选择性确认,重传机制是重传最后确认的TCP报文段后续的所有报文段,使用该选项则只会重传未确认的报文段
               5:SACK实际工作选项,告诉发送方本端已经收到并缓存的不连续数据块,块左边沿是块的第一个数据序号,右边沿是块最后一个字节的下一个序号,每个序号4B故块对是8B,最多有(40-2)/8=4个块可以告知对方,扩展最大长度40B减去kind和length共2B
               8:时间戳选项,提供了较为准确的计算通信双方之间的回路时间RTT从而为TCP流量控制提供重要的信息。
               以上选项可以在/proc/sys/net/ipv4/目录下设置内核参数
        length:包含kind和length在内的2B的该可选信息的总长度
       info:选项的具体信息
   半关闭状态:一端发送结束报文给对端但是还可以接收来自对端的数据直到对端发送来结束报文段结束连接。应用程序判断对方是否已经关闭的方法read系统调用返回0,shutdown函数支持半关闭但是很少应用程序采用半关闭
   iptable可以过滤数据包
   TCP连接超时:每次重连的超时时间都增加一倍且5次重连失败则放弃连接次数在/proc/sys/net/ipv4/tcp_syn_retries内核参数定义
   TCP状态转移图:
        服务器端:通过listen进入LISTEN状态一旦监听到某个连接请求就将该连接放入请求队列并向客户端发送带SYN标志的确认报文段,并将此连接状态处于SYN_RCVD状态,若服务器收到客户端发送回的确认报文段则该连接转移到ESTABLISHED状态此时连接双方能够进行双向数据传输。当客户端关闭连接(close或shutdown调用发送结束报文段),服务器返回确认报文段使连接进入CLOSE_WAIT状态(等待服务器应用程序关闭连接),服务器检测到客户端关闭连接后立即给客户端发送一个结束报文段来关闭连接,并使连接进入LAST_LACK状态以等待客北洋大学户端结束报文段的最后一次确认。
       客户端:通过connect建立连接向服务器发送一个同步报文段使连接转移到SYN_SENT状态,但connect调用失败有两个状态:conncet连接的目的端口不存在或者端口处于TIME_WAIT状态则服务器给客户端发送一个复位报文段(RST重新建立连接),若目的端口存在但connect在超时时间内未收到服务器的确认报文段。connect调用失败将使连接立即返回到初始的CLOSED状态,若connect调用成功连接转入ESTABLISHED装填。当客户端执行主动关闭时向服务器发送结束报文段同时连接进入FIN_WAIT_1状态,若此时收到服务器的确认报文段则连接转入FIN_WAIT_2,当客户端处于FIN_WAIT_2服务器处于CLOSE_WAIT状态可能发生半关闭状态(服务端)。若服务器也关闭连接并发送结束报文段则客户端确认进入TIME_WAIT状态。若客户端先收到服务器的结束报文段而不是服务器确认客户端的结束报文段则客户端可直接由FIN_WAIT_1进入TIME_WAIT。
      TIME_WAIT状态:客户端在收到服务器的结束报文段后不是直接进入CLOSED状态而是进入TIME_WAIT状态在这个状态客户端要等待2MSL(报文段最大生存时间)才能完全关闭,这样可以可靠地关闭连接,保证迟来的报文段在足够的时间内被丢弃。服务器端的知名服务器端口号可以使用socket选项REUSEADDR强制立即使用处于TIME_WAIT状态的端口。
      复位报文段中将窗口大小置为0对端收到后就关闭或重新连接而不能回应这个复位报文段。一旦发送了复位报文段,发送端所有排队等待发送的数据都将丢弃。socket的SO_LINGER选项发送复位报文段
      半打开连接:一端关闭或异常终止了连接而对方没有接收到结束报文段该连接处于半打开状态,此时另一端向连接写入数据一端则回应一个复位报文段
      延迟确认:不马上确认上次收到 的数据而是在一段延迟时间后查看本端是否有数据需要发送如果有则和确认信息一起发出
      Nagle算法:解决过多微小TCP报文段可能导致拥塞,要求一个TCP连接在一个时刻只能最多发送一个未被确认信息,在该确认信息未到达之前不能发送其它报文段,且在此期间内收集其它微量数据下次封装在一个报文段内。具有自适应性:确认达到得越快数据发送的越快
      带外数据:比普通数据具有更高的优先级应该被立即发送而不论发送缓冲区是否有排队等待发送的普通数据
      TCP超时重传:为每个TCP发送报文段启动一个重传定时器若在超时时间内未收到对方应答则新一轮重传,5次重传每次重传时间间隔时间增加一倍,和TCP超时重连类似
      TCP拥塞控制:接收端将自己的窗口大小RWND告知发送端限制发送端的速度,但这并没有考虑到网络本身的拥塞情况,在发送端定义拥塞窗口CWND,则发送端的实际窗口大小SWND=min(RWND,CWND),RWND由接收端控制,所以发送端必须考虑CWND。
              慢启动:CWND设置为一个初始值IW(可以为1,假设单位是发送端的报文段最大长度SMSS一般等于MSS),发送端开始按照拥塞窗口大小发送数据,每当有一个报文段被确认,cwnd就增加1个MSS大小。这样cwnd的值就随着网络往返时间(Round Trip Time,RTT)呈指数级增长,事实上,慢启动的速度一点也不慢,只是它的起点比较低一点而已。
             拥塞避免:从慢启动可以看到,cwnd可以很快的增长上来,从而最大程度利用网络带宽资源,但是cwnd不能一直这样无限增长下去,一定需要某个限制。TCP使用了一个叫慢启动门限(ssthresh)的变量,当cwnd超过该值后,慢启动过程结束,进入拥塞避免阶段。对于大多数TCP实现来说,ssthresh的值是65536(以字节计算)。拥塞避免的主要思想是加法增大,也就是cwnd的值不再指数级往上升,开始加法增加。此时当窗口中所有的报文段都被确认时,cwnd的大小加1,cwnd的值就随着RTT开始线性增加,这样就可以避免增长过快导致网络拥塞,慢慢的增加调整到网络的最佳值。
            拥塞控制:判断拥塞的两个依据:传输超时或者TCP重定时器溢出;接收到重复的确认报文段(比前者情况要好点毕竟还能收到确认报文段)
            快速重传(针对超时):1.把ssthresh降低为cwnd值的一半;2.把cwnd重新设置为1;3.重新进入慢启动过程。
            快速恢复(针对收到3个重复ack):1.把ssthresh设置为cwnd的一半;2.把cwnd再设置为ssthresh的值(具体实现有些为ssthresh+3);3.重新进入拥塞避免阶段。快速恢复的思想是“数据包守恒”原则,即同一个时刻在网络中的数据包数量是恒定的,只有当“老”数据包离开了网络后,才能向网络中发送一个“新”的数据包,如果发送方收到一个重复的ACK,那么根据TCP的ACK机制就表明有一个数据包离开了网络,于是cwnd加1。主要步骤是:1.当收到3个重复ACK时,把ssthresh设置为cwnd的一半,把cwnd设置为ssthresh的值加3,然后重传丢失的报文段,加3的原因是因为收到3个重复的ACK,表明有3个“老”的数据包离开了网络。
2.再收到重复的ACK时,拥塞窗口增加1。3.当收到新的数据包的ACK时,把cwnd设置为第一步中的ssthresh的值。原因是因为该ACK确认了新的数据,说明从重复ACK时的数据都已收到,该恢复过程已经结束,可以回到恢复之前的状态了,也即再次进入拥塞避免状态。
     Web客户端和服务端使用HTTP协议通信,HTTP是应用层协议默认使用传输层的TCP协议。
     lsof可以查看服务器程序监听的端口号,3128是sqiud(代理服务器程序)默认使用的端口号
     代理服务器:正向代理服务器:客户端自己设置代理服务器地址(如翻墙);反向代理服务器:设置在服务器端,将请求转发给内部网络上的服务器并将从内部获得的结果返回给客户端
     通过主机名访问机器时可以通过本地文件/ect/hosts查询某个主机名对应的IP地址,首先读取/etc/hosts配置文件试图通过它来解析主机名对应的IP地址,若未找到则查询DNS服务器,修改/etc/host.conf定义解析主机名的方法和顺序。Linux系统在向DNS服务器发出域名解析请求之前会查询/etc/hosts文件,如果里面有相应的记录,就会使用hosts里面的记录
HTTP请求:短连接同一个客户的多个连续的连接不能共用一个TCP连接,长连接指多个请求可以使用同一个TCP连接,HTTP请求和应答中的“Connect”头部字段就是专门用于告诉对方一个请求完成之后该如何处理连接的立即关闭值是“close”保持一段时间是“keep-live”。
      HTTP应答;Cookie是服务器发送给客户端的特殊信息,客户端每次向服务器发送请求的时候都需要带上这些信息,这样服务器就可以区分不同的客户了,浏览器的自动登陆就是基于Cookie的。

抱歉!评论已关闭.