ICMP不可达差错
当路由器收到一份应该要分片的数据报时,而在IP首部又设置了不分片的标识,此时就会产生ICMP不可达差错
这里的报文格式与之前的不同,在第2个32字节中,16~32bit提供下一站的MTU
UDP和ARP之间的交互作用
这里我们发送一个包含8129字节数据的UDP数据报,我们也能预测他会在以太网上产生6个数据报片,。
同时,我们保证arp高速缓存现在是空的,具体操作如下:
首先我们观察tcpdump的输出结果:
在得知tcpdump之前,我们可能会有的疑惑是,在接收到arp应答前,其余数据报是被如何处理的?
结果出乎意料,在第一个arp应答返回前,总共产生了6个arp请求,我们认为是IP很快产生了6个数据报片,而每个数据报片都引发了arp请求。
其次,在接收到第一个arp应答后,只发送了最后一个数据报片,前5个都被丢弃了。
事实上,这是正常的arp协议表现,大多实现中,在等待arp应答时,只将最后一个报文发送给特定目的主机。
这种情况称为 arp flooding,即以高速率重复发送到同一个IP地址的ARP请求。
而且关于ARP,要求其至少保留一个报文,且必须是最后一个报文。
在第一个数据报片(第一个到达的数据报片,并不一定要偏移量为0的所谓第一个数据报片)出现时,IP层必须启动一个定时器。如果定时器超时,但不是所有数据报片都到达,那么这些数据报片将被丢弃
ICMP源站抑制差错
我们也可以用UDP产生ICMP源站抑制差错
当一个系统接收数据报的速度比其处理速度快时,可能产生这个差错(这里说可能,说明有时即使丢弃数据报也不一定会发生源站抑制报文)
该报文的格式如下:
关于UDP服务器
UDP输入队列
通常程序所使用的每个UDP端口都与一个有限大小的输入队列相联系。这意味着,来自不同客户的差不多同时到达的请求将由UDP自动排队。接收到的UDP数据报以其接收顺序交给应用程序(应用程序会要求交送下一个数据报)
当然,排队溢出造成内核中的UDP模块丢失数据报也是可能的。
作者做了以下实验:
在bsdii主机上以UDP服务器的形式运行sock程序(这是作者自己写的):
在服务器运行后,其处于30秒的暂停时间内,此时我们在两台主机上交替发送数据报,
在sun主机上发送广播数据:
在svr4上发送数据:
注意,这里数据报是交替发送的,即在30秒内,sun发一个数据报,svr4发一个,共6份数据报
30秒后,我们发现在bsdi主机上发现:
只收到两份UDP数据报
这里我们再用tcpdump观察两个客户主机的发送数据:
可以看到12秒就发完了,在30秒内的
其次,所有数据报都发往服务器了
1、 这个例子里,可以看出应用程序并不知道其输入队列溢出了,只是由UDP模块对数据报进行了处理
2、 没有信息发回告诉客户其数据报被丢弃了
3、 没有ICMP源站抑制这样的消息
4、 UDP输出队列是FIFO的
限制本地IP地址
在编程中,我常常指定的是INADDR_ANY,指的是进入UDP数据报如果其目的地为服务器端口,那么本地任何接口都可以处理它
如果用netstat观察,结果一般会是这样:
当我们指定了接口就不一样了:
这种情况下,如果有一份数据报目的地址是本地主机的另一个地址,那么就会出错:
既然可以指定接口使用端口号,那在一台主机上就能在相同的端口上启动不同的服务器,每个服务器使用不同的本地IP地址,同一端口号,如下:
使用netstat观察有:
这就是需要在编程中指定SO_REUSEADDR选项了
这种情况下,如果数据包指定了特定IP地址,那么在匹配目的地址时始终优先匹配该IP地址,只有在匹配不成功时使用含星号的接口。
对于本地可以限制i,对于另一端也可以: