http://c.biancheng.net/view/6442.html
https://blog.csdn.net/Jailman/article/details/77574207
用UDP, 如果sendto发给server的某个port,但是server对应的端口上没有在receive,则非常可能返回一个icmp消息,提示端口不可达。 但是好像client端的socket是无法利用这个消息的,第二次发送还是显示成功。 就是说在UDP模式下,client端根本不知道server是不是在接收,除非一定要确认消息。
分析一种ICMP差错报文,即端口不可达报文,它是ICMP目的不可到达报文中的一种,以此来看一看ICMP差错报文中所附加的信息。UDP的规则之一是,如果收到一份UDP数据报而目的端口与某个正在使用的进程不相符,那么UDP返回一个ICMP不可达报文。UDP的规则之一是,如果收到一份UDP数据报而目的端口与某个正在使用的进程不相符,那么UDP返回一个ICMP不可达报文。
可以用TFTP来强制生成一个端口不可达报文。对于TFTP服务器来说,UDP的公共端口号是69。但是大多数的TFTP客户程序允许用connect命令来指定一个不同的端口号。这里,我们就用它来指定8888端口:
connect命令首先指定要连接的主机名及其端口号,接着用get命令来取文件。敲入get命令后,一份UDP数据报就发送到主机svr4上的8 8 8 8端口。
ICMP报文是在主机之间交换的,而不用目的端口号,而每个2 0字节的UDP数据报则是从一个特定端口(2924)发送到另一个特定端口(8 8 8 8)。跟在每个UDP后面的数字2 0指的是UDP数据报中的数据长度。
ICMP的一个规则是,ICMP差错报文,必须包括生成该差错报文的数据报I P首部,还必须至少包括跟在该I P首部后面的前8个字节。在我们的例子中,跟在IP首部后面的前8个字节包含UDP的首部。
一个重要的事实是包含在UDP首部中的内容是源端口号和目的端口号。就是由于目的端口号(8 8 8 8)才导致产生了ICMP端口不可达的差错报文。接收ICMP的系统可以根据源端口号(2 9 2 4)来把差错报文与某个特定的用户进程相关联(在本例中是TFTP客户程序)。
导致差错的数据报中的I P 首部要被送回的原因是因为IP首部中包含了协议字段,使得ICMP可以知道如何解释后面的8个字节(在本例中是UDP首部)。如果我们来查TCP首部,可以发现源端口和目的端口被包含在TCP首部的前8个字节中。
我们注意到有1 6种不同类型的ICMP不可达报文,代码分别从0到1 5。ICMP端口不可达差错代码是3。另外,尽管指出了在ICMP报文中的第二个32 bit字必须为0,但是当代码为4时(“需要分片但设置了不分片比特”),路径M T U发现机制却允许路由器把外出接口的MTU填在这个32 bit字的低16 bit中。尽管ICMP规则允许系统返回多于8个字节的产生差错的I P数据报中的数据,但是大多数从伯克利派生出来的系统只返回8个字节。Solaris 2.2 的i p _ i c m p _ r e t u r n _ d a t a _ b y t e s选项默认条件下返回前6 4个字节。