Socket的基本背景
在讨论这两个选项的区别时,我们需要知道的是BSD实现是所有socket实现的起源。基本上其他所有的系统某种程度上都参考了BSD socket实现(或者至少是其接口),然后开始了它们自己的独立发展进化。显然,BSD本身也是随着时间在不断发展变化的。所以较晚参考BSD的系统比较早参考BSD的系统多一些特性。所以理解BSD socket实现是理解其他socket实现的基石。下面我们就分析一下BSD socket实现。
在这之前,我们首先要明白如何唯一识别TCP/UDP连接。TCP/UDP是由以下五元组唯一地识别的:
{<protocol>, <src addr>, <src port>, <dest addr>, <dest port>}
这些数值组成的任何独特的组合可以唯一地确一个连接。那么,对于任意连接,这五个值都不能完全相同。否则的话操作系统就无法区别这些连接了。
一个socket的协议是在用socket()初始化的时候就设置好的。源地址(source address)和源端口(source port)在调用bind()的时候设置。目的地址(destination address)和目的端口(destination port)在调用connect()的时候设置。其中UDP是无连接的,UDP socket可以在未与目的端口连接的情况下使用。但UDP也可以在某些情况下先与目的地址和端口建立连接后使用。在使用无连接UDP发送数据的情况下,如果没有显式地调用bind(),草错系统会在第一次发送数据时自动将UDP socket与本机的地址和某个端口绑定(否则的话程序无法接受任何远程主机回复的数据)。同样的,一个没有绑定地址的TCP socket也会在建立连接时被自动绑定一个本机地址和端口。
如果我们手动绑定一个端口,我们可以将socket绑定至端口0,绑定至端口0的意思是让系统自己决定使用哪个端口(一般是从一组操作系统特定的提前决定的端口数范围中),所以也就是任何端口的意思。同样的,我们也可以使用一个通配符来让系统决定绑定哪个源地址(ipv4通配符为0.0.0.0,ipv6通配符为::)。而与端口不同的是,一个socket可以被绑定到主机上所有接口所对应的地址中的任意一个。基于连接在本socket的目的地址和路由表中对应的信息,操作系统将会选择合适的地址来绑定这个socket,并用这个地址来取代之前的通配符IP地址。
在默认情况下,任意两个socket不能被绑定在同一个源地址和源端口组合上。比如说我们将socketA绑定在A:X地址,将socketB绑定在B:Y地址,其中A和B是IP地址,X和Y是端口。那么在A==B的情况下X!=Y必须满足,在X==Y的情况下A!=B必须满足。需要注意的是,如果某一个socket被绑定在通配符IP地址下,那么事实上本机所有IP都会被系统认为与其绑定了。例如一个socket绑定了0.0.0.0:21,在这种情况下,任何其他socket不论选择哪一个具体的IP地址,其都不能再绑定在21端口下。因为通配符IP0.0.0.0与所有本地IP都冲突。
新闻热点
疑难解答