端口号在物理上没有指任何东西,范围是0~65535,它们被用于确定正确的接收数据的具体服务。对于客户机/服务器应用,一台服务器首先“绑定”到一个端口号,然后一个或多个客户机可使用某种特定的传输协议与一台服务器上的端口号建立连接。从这个意义上来说,端口号的功能更像电话号码的扩展,差别是它们通常是由某个标准来分配。
端口号并没有和应用有直接绑定关系,没有告诉协议栈数据要发送到哪个应用。大家说的端口号告诉TCP/UDP协议将报文发送给哪个进程并不正确。
在linux内核tcp/ip协议栈,端口号在多个地方用来作为hash索引。例如,一个服务器'绑定'某个端口,监听该socket的情况,内核建立一个listen端口的hash表,客户机调用connect时(带上服务器的ip,端口),服务器收到sync包会以报文的目标端口从hash表里查找,找到桶后,再通过源ip,源port,目标ip,目标port来匹配是否有重复的连接存在,如果没有,会在listen表里创建一个新的连接。这是端口标识服务的场景。另一场景是使用UDP协议,服务器同样需要'绑定'某个端口,客户端发送数据到服务器,服务器协议栈通过port索引找到socket,将数据写入socket数据队列中(多个客户机发送数据,服务器内核都是写入这同一个socket数据队列),服务应用通过fd读取数据;当第一次数据接收到数据后,服务端也就知道客户端的ip和port,应用可以使用客户端的ip和port进行回复;客户端内核同样维护着一张以port为索引的socket二维表,客户端在第一次发送数据后,内核会在表内加入socket元素,当客户端收到数据时,到传输层时,会以port为索引来查找,并使用ip,port(源ip,源port,目标ip,目标port)来匹配找到socket,将数据写入socket数据队列。
内核使用端口号做索引,寻找socket,对tcp服务器,监听的socket与接收数据的socket端口号相同,大家在不同的hash表,监听socket在监听表,接收数据socket在established表。
tcp协议客户端与服务器的socket有一对一的关系,所以叫
面向连接的;udp协议服务端只有一个socket,用它来接收多个客户端数据及发送数据给多个客户端,没有一对一对关系。