服务程序在listen某个端口并accept某个连接请求后,会生成一个新的socket来对该请求进行处理。

如果一个程序创建了一个socket,并让其监听80端口,其实是向TCP/IP协议栈声明了其对80端口的占有。以后,所有目标是80端口的TCP数据包都会转发给该程序(这里的程序,因为使用的是Socket编程接口,所以首先由Socket层来处理)。所谓accept函数,其实抽象的是TCP的连接建立过程。accept函数返回的新socket其实指代的是本次创建的连接,而一个连接是包括两部分信息的,一个是源IP和源端口,另一个是宿IP和宿端口。所以,accept可以产生多个不同的socket,而这些socket里包含的宿IP和宿端口是不变的,变化的只是源IP和源端口。这样的话,这些socket宿端口就可以都是80,而Socket层还是能根据源/宿对来准确地分辨出IP包和socket的归属关系,从而完成对TCP/IP协议的操作封装!


平时我们使用ServerSocket指定了某个端口(例如8080),然后多个客户端连接上socket之后就都用这个8080端口和服务器端通讯。或者http服务器使用80端口也是和多个浏览器进行连接通讯。为什么可以这样呢?操作系统的进程在同个端口的多个连接是如何进行分辨的?

我们这里讲Socket连接: 
1. 端口只是一个数字辨识,不是真正的物理端口; 
2. 一个Socket连接的主键(即不同socket之间的区分)是由一个五元组{SRC-IP, SRC-PORT, DEST-IP, DEST-PORT, PROTOCOL}组成,即{源地址,源端口,目标地址,目标端口,协议}组成,那些说四元组不包含协议的说法是错误的。 
3. 一个进程可以拥有多个socket连接。

例子一、两个客户端连接在同个服务器的同个端口80,即有两个socket连接: 
- socket1 {SRC-A, 100, DEST-X,80, TCP} 
- socket2{SRC-B, 100, DEST-X,80, TCP} 
主机A和主机B的地址不同,两台主机同时连接到服务器X的80端口。服务器要怎么处理这个连接是它的事,我们要理解的是为什么一个主机同个端口能监听多个客户端Socket连接。

解释: 
1. 是因为两个客户端的IP不同,服务器能识别出不同的Socket; 
2. 即使IP地址相同,端口不同,服务器也能够分辨; 
3. 只要服务器知道收到的请求和哪个socket相关,那么它就能使用这个socket正确地回复那个客户端; 
4. 如果对于不同的socket需要不同的端口,那么不仅仅浪费服务器资源,而且每次客户端连接上serverSocket之后还要另外分配新的端口和客户端通信。没必要。

例子二、不同的进程可以监听同一个端口。

  1. 因此在服务器的两个使用不同协议的进程可以监听同一个端口。
  2. 如果一个socket的辨识只是四元组不包括协议{SRC-IP, SRC-PORT, DEST-IP, DEST-PORT},那么不同进程是不可能同时监听同一个端口的。没有协议的话一个客户端连接到同一台某个有两个进程监听端口的服务器,那么就没有什么机制可以确定客户端是要连接哪一个进程了。

总结

  1. 不同协议可以监听同一个端口(不管是不是在服务器的同个进程)
  2. 某个协议的进程可以监听多个客户端的连接,因为只要五元组不同进程就能分辨。
  3. 从上面的例子可以知道,客户端同个进程也可以在同个端口用不同的协议与客户端建立连接。