发布于:,更新于:

进程与端口的关系

进程和端口的关系

Q:

都说端口号是操作系统进行抽象,用来定位一个进程。
当一台主机上有两张网卡时,每张网卡上绑定了一个IP地址。
那么如果访问不同IP地址的同一端口,比如80,应该不会定位到同一个程序吧。
那么端口号就应该是针对于每一张网卡进行的进程抽象,而不是操作系统对每一个进程的抽象吧?

A:

当计算机接收到报文时,需要将这个报文递交(Deliver)给某个特定的进程。

当有(1.1.1.1,50007)——–165364组合报文到达操作系统时,
1.1.1.1 是IP地址,50007是端口号,165364是进程号
稍后当操作系统TCP/IP协议栈接收到一个IP报文,
通过提取目的IP地址(位于IP头)、目的端口号(位于TCP头),
这两者的组合恰好为(1.1.1.1,50007)。

操作系统查询一下小本子,立马就得知这是(进程ID= 168324)进程A的,
然后通知该进程A前来将报文取走。

进程B也想如法炮制:Bind (‘1.1.1.1’, 50007),很遗憾,操作系统拒绝了。
拒绝的消息如下:
“builtins.OSError: [WinError 10048] 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。”
意味着(1.1.1.1, 50007)这个组合能唯一识别一个进程,这两者的组合就是一个主键

通俗地说,在数据库管理系统,主键可以唯一锁定一条记录。

进程B(进程ID= 168323)心有不甘,发现计算机还有其它接口地址2.2.2.2,于是通过Bind (‘2.2.2.2’, 50007),这次成功了。

操作系统老爷爷又颤颤巍巍掏出小本子记录了下来: (2.2.2.2,50007)——–168323
这样当有(2.2.2.2 , 50007)组合报文到达时,操作系统可以将其转交给(进程号= 168323)进程B。
问题来了,进程A与进程B是什么关系?
进程A、B可以是代码完全不同的程序,也可以是代码相同的程序,
在自己独立的内存空间运行的不同实列(Instance)。
好比你同时打开多个Word程序,这些Word程序使用相同的代码,但是他们是多个Word实例。

问题又来了,如果进程A的代码真的是那样编码,如果放到其它计算机上执行,会遇到问题,因为其它计算机的IP地址可能≠1.1.1.1。
为了提高代码的健壮性、可移植性,
通常会使用这样的代码: Bind (‘ ’, 50007) 其中‘’表示任何IP地址。
换句话说,不Care计算机的接口IP地址。
这个IP地址可以是127.0.0.1,也可以是1.1.1.1, 也可以是192.168.1.1,随便多少都行。
那么这个程序可以放到任何计算机上执行。
在同一台机器上一个进程B也这样执行:Bind (‘ ’, 50007),可以哇? 不可以,因为与进程A冲突!
进程B可以Bind (‘ 1.1.1.1’, 50007),可以哇?
同样不可以,依然与进程A冲突。因为1.1.1.1是所有IP地址的子集。

进程B心慌了,那怎么可以呢?
操作系统老爷爷不紧不慢地说,只要别再使用端口50007就可以了。

进程B于是执行代码如下: Bind (‘ ’, 50008), 可以哇? 恭喜你,当然可以!
通常服务器代码,都使用类似Bind (‘ ’, 50007) 方式执行,
所以50007这个端口号可以唯一识别一个进程,这就是端口号可以唯一识别进程号的由来!