TCP/IP 详解(卷一) TCP的超时与重传

TCP提供可靠的运输层。它使用的方法之一就是确认从另一端收到的数据。但数据和确认都有可能会丢失。TCP通过在发送时设置一个定时器来解决这种问题。如果当定时器溢出时还没有收到确认,它就重传该数据。对任何实现而言,关键之处就在于超时和重传的策略,即怎样决定超时间隔和如何确定重传的频率。

对每个连接,TCP管理4个不同的定时器。

  1. 重传定时器使用于当希望收到另一端的确认。
  2. 坚持(persist)定时器使窗口大小信息保持不断流动,即使另一端关闭了其接收窗口。
  3. 保活(keepalive)定时器可检测到一个空闲连接的另一端何时崩溃或重启。
  4. 2MSL定时器测量一个连接处于TIME_WAIT状态的时间。

Read More

Stylus 自定义网页字体

使用 Stylus 可以直接使用 userstyles 网站 提供的模板,很多下载后几乎不用设定即可使用,前提是现在电脑上安装相应的字体。

这里推荐一款 ForceMyFont 的模板,可以设定的选项非常丰富,前提也是需要在电脑上安装你选择的字体。

你也可以自定义字体CSS的样式,在 Chrome 浏览器中,这里使用 Stylus 插件,编写新的样式,代码如下:

*{font-weight:500!important;}
*{font-family: Arial, "思源宋体"!important;}

第一行设定字重,第二行设定英文字体和中文字体。如果要添加字体阴影,可以添加以下代码:

*{text-shadow:0.01em 0.01em 0.01em #999999 !important;}

其中的数值依次代表阴影的 X 轴偏移、Y 轴偏移、阴影大小,以及字体颜色。

Read More

TCP/IP 详解(卷一) TCP的成块数据流

TFTP使用了停止等待协议,数据发送方在发送下一个数据块之前需要等待接收对已发送数据的确认。TCP使用了被称为滑动窗口协议的另一种形式的流量控制方法。该协议允许发送方在停止并等待确认前可以连续发送多个分组。由于发送方不必每发一个分组就停下来等待确认,因此该协议可以加速数据的传输。

滑动窗口

接收方通告的窗口称为提出的窗口(offered window),发送方计算它的可用窗口,该窗口表明多少数据可以立即被发送。

当接收方确认数据后,这个滑动窗口不时地向右移动。窗口两个边沿的相对运动增加或减少了窗口的大小。我们使用三个术语来描述窗口左右边沿的运动:

  1. 称窗口左边沿向右边沿靠近为窗口合拢。这种现象发生在数据被发送和确认时。
  2. 当窗口右边沿向右移动时将允许发送更多的数据,我们称之为窗口张开。这种现象发生在另一端的接收进程读取已经确认的数据并释放了TCP的接收缓存时。
  3. 当右边沿向左移动时,我们称之为窗口收缩。Host Requirements RFC强烈建议不要使用这种方式。但TCP必须能够在某一端产生这种情况时进行处理。

Read More

TCP/IP 详解(卷一) TCP的交互数据流

一些有关TCP通信量的研究如[Caceres et al. 1991]发现,如果按照分组数量计算,约有一半的TCP报文段包含成块数据(如FTP、电子邮件和Usenet新闻),另一半则包含交互数据(如Telnet和Rlogin)。如果按字节计算,则成块数据与交互数据的比例约为90%和10%。这是因为成块数据的报文段基本上都是满长度(full-sized)的(通常为512字节的用户数据),而交互数据则小得多(上述研究表明Telnet和Rlogin分组中通常约90%左右的用户数据小于10个字节)。

很明显,TCP需要同时处理这两类数据,但使用的处理算法则有所不同。

交互式输入

首先来观察在一个Rlogin连接上键入一个交互命令时所产生的数据流。许多TCP/IP的初学者很吃惊地发现通常每一个交互按键都会产生一个数据分组,也就是说,每次从客户传到服务器的是一个字节的按键(而不是每次一行)。而且,Rlogin需要远程系统(服务器)回显我们(客户)键入的字符。这样就会产生4个报文段:(1)来自客户的交互按键;(2)来自服务器的按键确认;(3)来自服务器的按键回显;(4)来自客户的按键回显确认。

然而,我们一般可以将报文段2和3进行合并—按键确认与按键回显一起发送。

Read More

emacs 字体配置

定义设置中文和英文字体的函数,达到等宽效果:

(defun set-font()
  (interactive)
  
  ;; Setting English Font

  (when (member "DejaVu Sans Mono" (font-family-list))
    (set-face-attribute 'default nil :font
                        (format "%s:pixelsize=%d" "DejaVu Sans Mono" 14))
    )
  
  ;; Setting Chinese font

  (dolist (charset '(kana han symbol cjk-misc bopomofo))
    (set-fontset-font (frame-parameter nil 'font)
                      charset
                      (font-spec :family "Microsoft Yahei" :size 16))
    )
  
  ;; Fix chinese font width and rescale

  (setq face-font-rescale-alist '(("STHeiti" . 1.2) ("STFangsong" . 1.2) ("Microsoft Yahei" . 1.2) ("WenQuanYi Micro Hei Mono" . 1.2)))
  )

调用 set-font 函数可使设置生效:

(add-to-list 'after-make-frame-functions
             (lambda (new-frame)
               (select-frame new-frame)
               (if window-system
                   (set-font))))

(if window-system
    (set-font))

Read More

TCP/IP 详解(卷一) TCP连接的建立与终止

TCP是一个面向连接的协议。无论哪一方向另一方发送数据之前,都必须先在双方之间建立一条连接。这种两端间连接的建立与无连接协议如UDP不同。一端使用UDP向另一端发送数据报时,无需任何预先的握手。

两个进程在使用TCP交换数据之前,它们之间必须建立一条连接。完成后,要关闭这个连接。

一个TCP连接由一个4元组唯一确定:本地IP地址、本地端口号、远端IP地址和远端端口号。

Read More

TCP/IP 详解(卷一) TCP:传输控制协议

尽管TCP和UDP都使用相同的网络层(IP),TCP却向应用层提供与UDP完全不同的服务。TCP提供一种面向连接的、可靠的字节流服务。

面向连接意味着两个使用TCP的应用(通常是一个客户和一个服务器)在彼此交换数据之前必须先建立一个TCP连接。这一过程与打电话很相似,先拨号振铃,等待对方摘机说“喂”,然后才说明是谁。

在一个TCP连接中,仅有两方进行彼此通信。

TCP通过下列方式来提供可靠性:

  • 应用数据被分割成TCP认为最适合发送的数据块。这和UDP完全不同,应用程序产生的数据报长度将保持不变。由TCP传递给IP的信息单位称为报文段或段(segment)。
  • 当TCP发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。
  • 当TCP收到发自TCP连接另一端的数据,它将发送一个确认。这个确认不是立即发送,通常将推迟几分之一秒。
  • TCP将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP将丢弃这个报文段和不确认收到此报文段(希望发端超时并重发)。
  • 既然TCP报文段作为IP数据报来传输,而IP数据报的到达可能会失序,因此TCP报文段的到达也可能会失序。如果必要,TCP将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层。
  • 既然IP数据报会发生重复,TCP的接收端必须丢弃重复的数据。
  • TCP还能提供流量控制。TCP连接的每一方都有固定大小的缓冲空间。TCP的接收端只允许另一端发送接收端缓冲区所能接纳的数据。这将防止较快主机致使较慢主机的缓冲区溢出。

Read More

Markdown 复杂表格

由于Markdown语法本身不包含复杂表格的插入,但是可以使用html语法来实现,一般的Markdown编辑器都是支持html语法的。

复杂表格与简单表格最大的差异有两点:水平单元格的合并和纵向单元格的合并,通过html语法实现这两个操作本质就是:删除多余的空白单元格,然后使用某些单元格的colspan和rowspan属性进行扩展填充。

  • 水平单元格的合并:基于colspan属性,即使一个单元格占多列的空间。
  • 纵向单元格的合并:基于rowspan属性,即使一个单元格占多行的空间。

可以从Word或者Excel中复制表格,通过网站 No-Cruft Excel to HTML Table Converter 转换获得html代码。

Read More

TCP/IP 详解(卷一) BOOTP:引导程序协议

一个无盘系统,它在不知道自身IP地址的情况下,在进行系统引导时能够通过RARP来获取它的IP地址。然而使用RARP有两个问题:(1)IP地址是返回的唯一结果;(2)既然RARP使用链路层广播,RARP请求就不会被路由器转发(迫使每个实际网络设置一个RARP服务器)。下面将介绍一种用于无盘系统进行系统引导的替代方法,又称为引导程序协议,或BOOTP。

BOOTP使用UDP,且通常需与TFTP协同工作。

BOOTP 的分组格式

BOOTP 请求和应答均被封装在UDP数据报中,IP首部(20字节) - UDP首部(8字节) - BOOTP请求/应答(300字节)。

“操作码”字段为1表示请求,为2表示应答。硬件类型字段为1表示10 Mb/s的以太网,这和ARP请求或应答中同名字段表示的含义相同。类似地,对于以太网,硬件地址长度字段为6字节。

“跳数”字段由客户设置为0,但也能被一个代理服务器设置。

“事务标识”字段是一个由客户设置并由服务器返回的32 bit整数。客户用它对请求和应答进行匹配。对每个请求,客户应该将该字段设置为一个随机数。

客户开始进行引导时,将“秒数”字段设置为一个时间值。服务器能够看到这个时间值,备用服务器在等待时间超过这个时间值后才会响应客户的请求,这意味着主服务器没有启动。

Read More

TCP/IP 详解(卷一) TFTP:简单文件传送协议

TFTP(Trivial File Transfer Protocol)即简单文件传送协议,最初打算用于引导无盘系统(通常是工作站或X终端)。为了保持简单和短小,TFTP将使用UDP。TFTP的代码(和它所需要的UDP、IP和设备驱动程序)都能适合只读存储器。

协议

在开始工作时,TFTP的客户与服务器交换信息,客户发送一个读请求或写请求给服务器。在一个无盘系统进行系统引导的正常情况下,第一个请求是读请求(RRQ)。下图显示了5种TFTP报文格式(操作码为1和2的报文使用相同的格式)。

TFTP报文的头两个字节表示操作码。对于读请求和写请求(WRQ),文件名字段说明客户要读或写的位于服务器上的文件。这个文件字段以0字节作为结束。模式字段是一个ASCII码串netascii或octet(可大小写任意组合),同样以0字节结束。netascii表示数据是以成行的ASCII码字符组成,以两个字节—回车字符后跟换行字符(称为CR/LF)作为行结束符。这两个行结束字符在这种格式和本地主机使用的行定界符之间进行转化。octet则将数据看作8bit一组的字节流而不作任何解释。

每个数据分组包含一个块编号字段,它以后要在确认分组中使用。以读一个文件作为例子,TFTP客户需要发送一个读请求说明要读的文件名和文件模式(mode)。如果这个文件能被这个客户读取,TFTP服务器就返回一个块编号为1的数据分组。TFTP客户又发送一个块编号为1的ACK。TFTP服务器随后发送块编号为2的数据。TFTP客户发回块编号为2的ACK。重复这个过程直到这个文件传送完。除了最后一个数据分组可含有不足512字节的数据,其他每个数据分组均含有512字节的数据。当TFTP客户收到一个不足512字节的数据分组,就知道它收到最后一个数据分组。

Read More