端口是什么意思?(了解什么是端口)
admin
2023-10-25 18:21:58
0

每当看到有人的简历上说自己熟悉tcp/ip、http等协议,就忍不住问他们:告诉我港口是什么!不幸的是,很少有人能说得令人满意.那么我们来说说port,一个熟悉的陌生人。

在这个过程中,我们还会讲到间接层、namingservice、IoC、依赖反转的概念以及TCP协议的一些关键知识。

常见端口

在我们的日常开发过程中,尤其是后端开发人员,即使他并没有真正了解端口的细节,他还是会听到看到各种各样的端口。这个东西几乎无处不在,比如:

Mysql的默认端口是3306,redis的端口是6379,tomcat的默认端口是8080,ssh的端口是22,以此类推.当然我们最关心的还是web相关的端口,主要涉及80和443端口。下面就重点介绍一下。

端口是必须的吗?

在本地web开发和调试的过程中,我们可能都会遇到端口,比如可能最著名的端口8080。通常,我们将通过这种方式访问本地web程序3360。

本地主机:8080

但是一旦web程序部署到正规网站,端口似乎就消失了。正规网站是不是不需要端口?答案是否定的,这里起作用的是默认值。

例如,如果你访问我的网站:https://xiaogd.net,在这个网址似乎没有端口,但有一个。它的默认值是443,所以完整的形式实际上是3360。

https://xiaogd.net:443

你可以通过Chrome的开发者调试工具看到这一点。

如您所见,ip地址后面是443。

如果你输入了一个错误的端口,比如80,像这个:https://xiaogd.net:80,结果就是无法访问。

但如果改成http://xiaogd.net:80,又可以访问了。

注意,由于我的服务器配置了后台自动跳转到https的301重定向http,浏览器最终会再次跳转到https://xiaogd.net:443。

注意检查“Preservelog”来保存日志。您可以看到,端口80的第一个请求将得到301跳转的响应,并在Location字段中指示跳转目标,即https请求。浏览器接收到这个跳转指令,重新发起https请求,也就是图中第二个xiaogd.net的请求。所以地址栏最终会变成https,特此说明。

此时,如果输入http://xiaogd.net:443,则无法再次访问。

那么原因是什么呢?找到规律了吗?

注意一个是http,一个是https。

协议的缺省端口

当你没有在url中明确输入端口时,浏览器实际上会根据使用的协议为你指定一个默认端口:

如果是http协议,使用端口80。如果是https协议,使用端口443。如果自己进港呢?然后用你输入的端口,你输入什么就是什么。如果你打错了,如果你不能访问它,这是你的责任。谁让你鬼混的?

你本来不用这么麻烦的,但是你要脱裤子放屁。也许只是画蛇添足,弄巧成拙。

例如,如果使用http但输入443,或者使用https但输入80,则无法成功访问。

另外,如果你随便输入一个9527,http://xiaogd.net:9527这样的数字,自然是无法访问的,原因很简单,因为我的服务器根本没有在监听9527端口。

即使我在9527端口监听,也不一定是web服务,使用的协议可能既不是http也不是https,所以你尝试用浏览器访问可能会碰壁。

当然,我完全可以在服务器的端口9527上部署另一个web服务。例如,我可以将apache或tomcatserver之类的web服务器放在该端口上进行侦听,然后我可以通过防火墙和安全组访问它。我没有那样做。

那么为什么大家不在那些奇怪的端口上提供web服务呢?原因其实很简单,为了方便用户,也减轻用户的认知负担。

其实关于用户,你只需要记住两点。

用户是傻瓜,用户是懒惰的深刻地理解了这一点,你才可能成为一个好的程序员(包括但不限于产品经理,设计师...).

其实不仅仅是省略端口。看当前地址栏。不仅省略了HTTP、HTTPS等协议,还省略了末尾的斜杠/,甚至省略了www。

是的,我还救了你。事实上,你可以通过https://www.xiaogd.net/,访问它,但如果你可以通过https://xiaogd.net/,访问它,为什么还要再次输入三个呢?

个达不溜呢?

必须得承认,缺省的存在是有很大的帮助的,这其实是进步;但另一方面,这些缺省有时也会给不明就里的开发人员带来了一些困惑,好像端口不是必要的,但其实不是这样的.

为什么需要端口?

那为什么一定要端口这个东西呢?它到底起了什么作用,想必很多同学想要了解,下面就来说说为什么,而一个首先需要了解的概念就是进程间通讯(所谓的IPC(inter-processcommunication)

进程间通讯(IPC)

你在浏览器地址栏输入某个网站的域名,然后回车,就生成了一次请求,然后服务器响应你的请求,浏览器再把结果渲染出来,你就能最终看到到一个网页.

如果你曾经ping过一个域名,比如你现在ping我的域名xiaogd.net,你就能得到一个ip地址,118.89.55.54:

有了ip,浏览器自然就能找到我的主机,但还是有个问题,我的主机上运行着好多的进程,好多的服务,除了最常见的web服务,我可能还有ftp服务,mysql服务等等不一而足.

简单地讲,如果一个请求只有ip地址这一信息,操作系统将不知道把这个请求交给哪个进程去处理,如果是你来设计整个系统,你想象一下,是不是这样?

如果你仅仅是输入域名,经过DNS解析后,只能得到一个IP地址.

所谓的一次请求,从一个比较底层的角度去看,就是一次进程间的通讯.

它可以是navicat客户端与mysql数据库服务的一次通讯,也可以是winScp客户端与vsftpdFTP服务的一次通讯等等.

以上面的具体为例,可以说就是Chrome浏览器这个本地操作系统上的进程与我的服务器上的一个叫做Nginx的进程间的一次通讯.

那么,所谓的端口,其实可以简单地视作为进程ID.

当然,它与进程ID还是有不同的,下面再分析,或者目前你可以认为端口就是进程ID的影子.

也即是说,如果仅有域名(ip),是无法定位到一个进程的,通讯的发起方不但需要给出ip,还需要给出端口,只有这样,服务器才能知道由哪个进程去响应.

端口,一个间接层

那么问题又来了,为什么引入端口,而不是直接使用进程ID呢?这个原因想想也不难明白,大概有这么几点原因:

作为客户端无法知道服务端对应进程的ID服务端对应进程重启后ID会改变一个网站的web进程ID是这个,另一个网站的可能又是另一个

自然,原因是很多的,我也是随便的列举了一些,你或许还能想到更多.而为了解决这些个问题,就引入了端口这一间接层(indirection).

计算机世界里有一句名言:任何计算机问题均可通过增加一个间接(indirection)层来解决.(Anyproblemincomputersciencecanbesolvedwithanotherlayerofindirection.--DavidWheeler)

这个名言其实还有后面一句:Butwhatusuallywillcreateanotherproblem.(但通常会带来另一个问题)

这里所谓另一个问题,比如它会使得层次结构复杂化,交互效率下降等等.当然了,这就是架构师们要去权衡的问题了,很多时候,架构就是关于平衡的艺术.打死都不肯引入任何的间接层,这是一个极端;而一上来就引入好多个间接层,这又是另一个极端.

如果没有这个间接层,客户端要与服务端通讯,就要知道服务端对应进程的ID,也即是客户端是依赖于服务端的:

显然,这种模式对于web这种一个服务端对应大量客户端访问的情形是极不适应的,你都不知道有谁可能会来访问你的网站!你根本无法告诉它们.

而有了端口这一间接层,对于web的情形,这种依赖被倒置了,客户端总是把请求发送到80(或443)端口,这些成为标准的一部分,并要求服务端反过来去适应,服务端去监听端口的通讯并处理,变成了一种反向依赖.

如果一个进程想要提供web服务,它启动之后就要去绑定(binding)web相关的端口,

如果端口已经被其它进程绑定了(即所谓占用了),就会绑定失败;又或者被自身前一个未完全退出的进程占据着,也会绑定失败,在开发过程中你可能会遇到类似的问题,一个web进程没有关闭,你又试图启动另一个,而两者都用了相同的端口,就会产生冲突.

并在其上持续的监听(listen),同时在有请求到来的时候去响应(response).这样一来,进程ID的问题就消解了:

这类似于一个接口回调,浏览器只需要面向接口索取服务,而无需知道接口服务的具体提供者,这些细节被端口层所封装并隐藏起来了.

端口这一间接层的存在解耦(decouple)了客户端与服务端之间的强依赖,整个体系变得很灵活.

可以把端口视作一般编程概念中的接口(interface),而想Nginx,apache,tomcat等等可以认为是这个接口的不同实现(Implementation).

端口与现实世界的一个类比

为加深理解,可以举一个现实世界中的例子.相信大家都有过去市民中心办事的经历,比如去办理居住证,护照,社保等等业务,你通常会收到一个小纸条让你去某个窗口办理对应业务,这个窗口其实就类似于端口了:

比如80窗口就对应港澳台通行证业务

那么你要办港澳台通行证,你就奔向80号窗口就完了.你不要去问门口保卫处的王大爷,到底是哪位同志办理这个业务.

今天可能是小明在办理,隔了几天,小明可能受伤了,流血了,又轮到小红在那里办理,又过段时间,小红也出意外了,流产了,又轮到小张在办理,又过段时间,小张被发现在办理业务过程中徇私舞弊,流放了...

等等,如果此时你的同事问你怎么办港澳台通行证,你需要知道这些个人事变动的细节吗?根本不需要呀,你只需告诉他去80号窗口办理就好了...

市民中心的整个体系,会确保有个会办理这些业务的人员坐在那个窗口下面,你唯一需要做的,就是到那个窗口下请求服务即可.

端口与名称服务(namingservice)

通过上面现实世界类比的例子,对于端口的机制,相信你已经理解得比较深入了.广义上讲,端口层也可以视作一个namingservice(名称服务),这与比如springcloud中的eureka里的机制本质上是一样的,只是这个name就是一个抽象的数字,比如80.80就代表了一个web服务,Nginx之类的webserver绑定并监听就相当于把自身提供的web服务注册于其上.

DNS域名系统其实也是namingservice,你通过xiaogd.net这个名字(name),就能获取到我所提供给你的网页服务.

类似的还有java里的JNDI等,把一个名字与一个服务关联起来,比如一个名字就代表一个数据源(数据库连接)之类的.

端口与IoC(控制反转)

广义上,端口的上述机制也是控制反转(Ioc:InversionofControl)思想的一种体现,如果客户端需要知道服务端的进程ID,实际上就被服务端控制了,毕竟我服务端在哪个ID上提供服务,你就得把你的请求发到相应的ID上来;

而有了端口这一中间层呢?作为客户端,总是把请求发到对应端口上,并要求服务端绑定并监听那些端口以及作出响应,你服务端是反过来被我客户端所控制,我客户端发到哪个端口,你服务端就要去相应端口上监听并响应.

大家可以体会一下这种转变.这种设计或思想在编程领域其实是特别重要的,在很多其它地方都有体现.

因为浏览器总是把web请求发到了80或443端口,这就要求一个webserver进程去监听这些端口.比如在我的服务器上,webserver是Nginx,它启动之后就会去监听80和443端口,任何想要访问我的主页的人,并不需要知道我的Nginx进程ID是啥,借助于端口这一间接层,你就能够与我的Nginx进程通讯,并获取你想要的东西.

事实上你可以这么认为,浏览器实际上只是在与端口通讯,端口层再把这些请求委托(delegate)或代理(proxy)给相应的webserver去处理,端口的角色就是一个中间人,一个间接层.

再论缺省端口

现在,我们应该明白了,端口是必要的了,当然,对最终的用户来说,则不需要知道这些实现的细节,对于他们,应该遵循最小知识原则,知道得越少越好.

如果你一定要让用户在输入url的过程中输入端口,又或者要输入个www等等,用户就要给你扔过来"十万个为什么"了...

为什么要加个443?

为什么不是334,443是啥意思?

为什么一会儿是80,一会儿又是443?

为什么加个www,啥意思?

为什么末尾还加个斜杠,不加会死吗?

...

惹不起,惹不起...

还记得前面说的,用户是笨蛋,用户是懒汉吗?

这里又要引用一句计算机世界的名言了:程序员和上帝打赌要开发出更大更好连傻瓜都会用的软件,而上帝却总能创造出更大更傻的傻瓜。目前为止,上帝赢了。

ProgrammersareinaracewiththeUniversetocreatebiggerandbetteridiot-proofprograms.TheUniverseistryingtocreatebiggerandbetteridiots.SofartheUniverseiswinning.

说句心里话,很多时候,用户能记住你的域名就阿弥陀佛了,你就该烧高香了,你还想用户记住你的端口,真的想多了...

另一方面,说到这里我们应该也能明白了,那就是理论上,web服务实际上可以构建在任何端口之上.比如在本地开发的时候,用户只有你自己,那当然你可以随便挑一个端口,比如8080,只要自己知道就好了或顶多告诉另一个与你配合的前端同事.

同理,其它非web的服务,比如ftp服务,也不一定说非得在21端口上等等;mysql服务的端口同样可以调整为3306之外的端口.

又或者说,你想提供一个服务,但只想小范围内的人知道,你可以挑一个很偏门的端口,这样一般人只输一个域名就没法访问到你的服务了.

比如有人想偷偷提供一些服务,放一些广淫民群众喜闻乐见的小视频啥的...刑法警告,后果自负!!别说我没有提醒你.

端口与TCP/UDP协议

前面一直在说,什么3306端口,80端口,443端口,其实严格来说,端口是分TCP端口和UDP端口的,不过多数时候遇到的都是TCP端口,但TCP80端口和UDP80端口是不同的端口.

UDP的80端口,包括443端口其实被保留了,目前的http协议只构建在TCP协议之上.

当然,理论上讲,在UDP上构建http也不能说就完全不行,毕竟,无论UDP还是TCP都是构建在IP协议之上,总之呢,计算机的世界没什么是不可能的,而且似乎真有人在做这些尝试,不过这就属于两小母牛对屁股--比较牛逼的范畴了,深水区了,咱也不懂,不多说了.

还有一点,对于进程间的端口通讯,实际上是对称的,也即是说,服务器的响应也是先回到一个客户端的端口上.

如果你用Windows10系统,可以在任务管理器>性能>打开资源监视器>网络>TCP连接,点击下远程端口可以按照从小到大排列,通常就可以看到443的相关连接了,可以看到左边有一栏本地端口,一个TCP连接总是有一个远程端口,一个本地端口:

当发起一个TCP连接时,客户端首先自己先随机挑选一个没有被使用的端口作为服务器响应的接收端口,比如38672.在一个TCP的包里,无论是握手包还是后续的数据包,包头部分最重要的两个字段,一个就是源端口(sourceport),比如38672;另一个就是目标端口(destinationport),比如80,或者443.

可以这样看,服务器的响应也是先回到源端口,比如38672上,源端口再转给最终的进程,比如浏览器.

而对于一个IP包,同样的,包头部分最重要的两个字段,一个就是源IP(sourceIP);另一个就是目标IP(destinationIP).

而TCP包会作为IP包的数据包被打包到IP包里面,也一个IP包里其实包含了IP+端口.

IP加端口再加上端口与进程间的关联,分属两个不同主机间的进程就能通过TCP(UDP)/IP协议愉快地进行进程间的通讯(IPC)了.

当然了,同一个主机间的进程也同样可以利用这套机制.但同一个主机间还可以有其它选择,这个具体看各个操作系统是否提供相关机制及支持.而TCP/IP属于广泛应用的标准协议,从而得到了广泛支持.

因为篇幅关系,关于这样TCP协议等的细节,以及包括Socket,连接等概念,以及虚拟主机,反向代理等等就不再展开去说,如果你感兴趣,欢迎留言,后续会考虑再写一些文章去介绍.

同样因为篇幅的原因以及同时我也不是计算机网络及协议方面的专家,关于端口方面的,如果有什么说得不到位,或不正确的地方,欢迎留言指正,关于端口方面的介绍就到这里.

相关内容

热门资讯

重大通报,金花房卡出售/钻石大... 今 日消息,钻石大厅房卡添加微信33549083 苹果今日发布了 iOS 16.1 正式版更新,简单...
正版授权!牛牛充值房卡/火星大... 今 日消息,火星大厅房卡添加微信33549083 苹果今日发布了 iOS 16.1 正式版更新,简单...
(辅助挂实测)星悦云南丽江卡二... 自定义星悦云南丽江卡二辅助工具系统规律,只需要输入自己想要的开挂功能,一键便可以生成出星悦云南丽江卡...
实测分享“新甘孜斗牛透视挂辅助... 您好:新甘孜斗牛这款游戏可以开挂,确实是有挂的,需要软件加微信【8700483】,很多玩家在新甘孜斗...
正版授权!斗牛房间怎么创建的/... 正版授权!斗牛房间怎么创建的/水仙大厅房卡是在哪里买的水仙大厅是一款非常受欢迎的游戏,咨询房/卡添加...