知乐空间

深入理解什么是端口(port)(端口是什么)

什么是端口(更好地理解什么是端口)

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

在这个过程中,我们还会讲到间接层、命名服务、IoC、依赖倒置的概念以及TCP协议的一些关键知识。

公共端口

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

Mysql默认端口3306,

redis的6379端口,

Tomcat的默认8080端口,

22 ssh端口,

等等...

当然我们最关心的还是web相关的端口,主要涉及80和443端口。下面就重点介绍一下。

港口有必要吗?

在本地web开发调试的过程中,我们可能都会遇到端口,比如也许/最著名的8080端口。一般来说,我们会像这样访问本地web程序:

本地主机:8080

但是web程序一旦部署到官网,端口好像就消失了,那么官网里就不需要端口了吗?答案是否定的,这里起作用的是默认值。

例如,如果你访问我的网站:https://xiaogd.net,这个网址中似乎没有端口,但它有。它的默认值为443,因此完整的表单实际上如下所示:

https://xiaogd.net:443。

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

您可以看到ip地址后面是443。

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

但是如果你把它换成http://xiaogd.net:80,它还可以再去。

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

注意选中“保存日志”来保存日志。您可以看到,端口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或tomcat server之类的web服务器放在该端口上侦听,然后让通过防火墙、安全组等等,这也是可访问的。我就是没做。

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

实际上,你只需要记住关于用户的两件事:

用户是傻子。

用户懒惰。

只有深刻理解这一点,你才能成为一名优秀的程序员(包括但不限于产品经理、设计师...)

实际上省略了端口。现在看看地址栏。不仅省略了http、https的协议,还省略了最后一个斜杠/斜杠,甚至连www都省略了。...

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

必须承认,违约的存在是有很大帮助的,这其实是进步;另一方面,这些默认有时候会给不了解的开发者带来一些困惑,好像端口不是必须的,其实不是。

为什么我需要一个端口?

那你为什么要移植这个东西?起到什么作用?我想很多同学都想知道。先说为什么。首先需要知道的概念之一IPC(进程间通信(所谓IPC)。

进程间通信

您在浏览器的地址栏中输入网站的域名,然后按enter生成请求。然后服务器响应你的请求,浏览器渲染结果,让你最终看到一个网页。

如果你曾经ping一个域名,例如,如果你现在ping我的域名xiaogd.net,你可以得到一个ip地址,118.89.55.54:

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

简单来说,如果一个请求只有ip地址的信息,操作系统就不知道把它交给哪个进程。如果你设计了整个系统,想象一下,不是吗?

如果只是输入域名,DNS解析后只能得到一个IP地址。

所谓一个请求,从相对较低的层面来看,就是一个进程间的通信。

可以是navicat客户端与mysql数据库服务之间的通信,也可以是winScp客户端与vsftpd FTP服务之间的通信等。

拿上面的具体例子来说,可以说是Chrome浏览器上的一个进程,一个本地操作系统,和我的服务器上一个叫Nginx的进程之间的通信。

那么,所谓的端口就可以简单的看成是进程ID。

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

也就是说,如果只有域名(ip),是无法定位进程的。通信的发起者不仅需要给出ip,还需要给出端口。只有这样,服务器才能知道哪个进程会响应。

端口,间接层

那么问题又来了。为什么要引入端口而不是直接使用进程ID?这个道理不难理解。大概有几个原因:

因为客户端不知道对应于服务器的进程的ID。

重新启动后,相应服务器进程的ID会发生变化。

一个网站的web进程ID是这个,另一个网站的可能是另一个。

自然有很多原因,我只是随便列举了一部分,你可能会想到更多。为了解决这些问题,引入了端口的间接层(间接)。

计算机界有句名言:任何计算机问题都可以通过增加一个间接层来解决。(计算机科学中的任何问题都可以通过另一层指示来解决。——大卫·惠勒)

其实这句名言背后还有另一句话:但究竟会产生什么另一个问题。(但通常会带来另一个问题)

这里还有一个问题,比如会使层级结构复杂化,降低交互效率等。当然,这是建筑师要权衡的问题。在很多情况下,建筑是平衡的艺术。拒绝引入任何间接层都是一种极端。一开始引入很多间接层,这是另一个极端。

没有这个间接层,客户端要想和服务器通信,就需要知道服务器对应的进程的ID,也就是客户端依赖于服务器:

显然,这种模式极不适合一台服务器对应大量客户端访问web,你不知道谁可能会访问你的网站的情况!你根本不能告诉他们。

而有了端口的间接层,在web的情况下,这种依赖就反过来了,客户端总是向端口80(或者443)发送请求,这就成了标准的一部分,要求服务器反过来适配,服务器监听处理端口的通信,就成了反向依赖。

如果一个进程想要提供web服务,它应该在启动后解除与web相关端口的绑定。

如果端口已经被其他进程绑定(所谓被占用),绑定会失败;或者它被尚未完全退出的前一个进程占用,绑定将失败。在开发过程中,你可能会遇到类似的问题。如果一个web进程没有关闭,而您试图启动另一个进程,并且这两个进程使用同一个端口,就会发生冲突。

并持续监听它,当请求到来时作出响应。这样,进程ID的问题就解决了:

这类似于接口回调。浏览器只需要请求接口的服务,不需要知道接口服务的具体提供者。这些细节被端口层封装和隐藏。

端口间接层的存在解耦了客户端和服务器之间的强依赖性,整个系统变得非常灵活。

端口可以看作是通用编程概念中的一个接口,而Nginx、apache、tomcat等可以看作是这个接口的不同实现。

港口和现实世界之间的类比

为了加深理解,我们可以举一个现实世界中的例子。相信大家都有过去在市民中心办理事务的经历,比如办理居住证、护照、社保等等。你一般会收到一张小纸条,要求你去一个窗口办理相应的业务。这个窗口实际上类似于一个端口:

比如窗口80对应的是港澳台护照业务。

那么,如果你想办理港澳台护照,你只要跑到80号窗口就可以了。不要问门口保卫处的王大爷是谁负责这个业务的。

今天,小明可能正在处理它。过几天小明可能会受伤出血,那边就轮到小红处理了。过了一会儿,小红也出事流产了,轮到小张处理了。过了一段时间,小张被发现在办理业务过程中徇私舞弊,被流放。...

等等,如果这时候同事问你港澳台通行证怎么办,你需要了解这些个人变动的细节吗?完全不需要,告诉他去80号窗口办理就行了。...

市民中心的整个系统将确保一个能够处理这些业务的人坐在那个窗口下。你唯一需要做的就是在那个窗口下请求服务。

端口和名称服务(命名服务)

通过上面真实世界类比的例子,相信你已经深刻理解了端口的机制。从广义上来说,端口层也可以看作是一个命名服务,本质上和spring cloud中的eureka中的机制是一样的,例如,除了名称是一个抽象的数字。80.比如80,代表web服务,绑定和监控Nginx等web服务器,就相当于在上面注册了自己提供的web服务。

DNS域名系统其实就是命名服务。你可以通过xiaogd.net这个名字获得我提供给你的网络服务。

类似地,java中的JNDI将名称与服务相关联,例如代表数据源(数据库连接)的名称。

和端口IoC(控制反转)

广义来说,端口的上述机制也是Ioc思想的一种体现:控制反转)。如果客户端需要知道服务器的进程ID,实际上是由服务器控制的。毕竟我的服务器在哪个ID上提供服务,你都要把你的请求发送到对应的ID上。

和中间层的端口?作为客户端,它总是向相应的端口发送请求,并要求服务器绑定、监控和响应这些端口。你的服务器反过来由我的客户端控制,无论我的客户端发送到哪个端口,你的服务器都会监控并响应相应的端口。

你可以体验这种转变。这种设计或者理念其实在编程领域是非常重要的,在其他很多地方也有体现。

因为浏览器总是向端口80或443发送web请求,所以这需要一个web服务器进程来监听这些端口。比如我的服务器上,web服务器是Nginx,启动后会监听端口80和443。任何想访问我主页的人都不需要知道我的Nginx进程ID是什么。借助端口的间接层,你可以和我的Nginx进程通信,得到你想要的。

其实你可以这么想。浏览器实际上只与端口通信。端口层将这些请求委托或代理给相应的web服务器。港口的作用是中间人和间接层。

再论默认端口

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

如果在输入url的过程中必须让用户输入端口,或者输入www等。,用户会扔给你“十万个为什么”...

为什么要加一个443?

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

为什么现在是80,现在是443?

为什么要加一个www?你什么意思?

为什么要在末尾加斜线?不加会死吗?

...

惹不起...

还记得我前面说的,用户是傻逼,用户是懒鬼吗?

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

程序员正在与宇宙赛跑,创造更大更好的防白痴程序。宇宙试图创造更大更好的白痴。到目前为止,宇宙赢了。

说实话,很多时候,用户能记住你的域名,那你就该烧香了,你想让用户记住你的端口。你真是想多了。...

另一方面,我们在这里应该能够理解,即理论上,web服务可以构建在几乎任何端口上。比如本地开发的时候,用户只有你自己,那么当然你可以随便挑一个端口,比如8080,只要你知道或者最多告诉另一个和你合作的前端同事。

类似地,其他非web服务,如ftp服务,不一定必须在端口21上,等等。mysql服务的端口也可以调整为3306以外的端口。

换句话说,你想提供一个服务,只是想让小范围内的人知道,你可以选择一个很偏的端口,让普通人只输入一个域名就无法访问你的服务。

比如有人想偷偷提供一些服务,放一些受广大好色人士欢迎的小视频...刑法警告,后果自负!!别说我没警告过你。

端口和TCP/UDP协议

我一直在说3306端口,80端口,443端口。其实严格来说,有两个端口:TCP端口和UDP端口。但是大多数时候遇到的都是TCP端口,只是TCP端口80和UDP端口80是不同的端口。

UDP端口80,包括端口443,实际上是保留的,目前的http协议只是建立在TCP协议上。

当然,从理论上讲,在UDP上构建http是不可能的。毕竟UDP和TCP都是建立在IP协议上的。总之,计算机世界里没有什么是不可能的,而且好像真的有人在做这些尝试,但这属于“两头小母牛对屁股”的范畴,深水区,我不懂,不多说了。

还有一点就是,进程之间的端口通信其实是对称的,也就是说,服务器的响应首先返回到一个客户端的端口。

如果使用Windows 10系统,可以在任务管理器>性能>打开资源监视器>网络> TCP连接中点击远程端口,通常可以看到443的相关连接。您可以在左侧看到一列本地端口。TCP连接总是有一个远程端口和一个本地端口:

当发起TCP连接时,客户端首先随机选择一个未使用的端口作为服务器响应的接收端口,比如38672。在一个TCP包中,不管是握手包还是后续包,头部分最重要的两个字段都是源端口,比如38672。另一种是目的端口,如80或443。

从这个角度来说,服务器的响应也是回到源端口,比如38672,然后源端口转发到最后的进程,比如浏览器。

类似地,对于IP分组,报头部分中的两个最重要的字段是IP(源IP;另一个是IP(目的IP。

TCP包会打包成IP包作为IP包,一个IP包实际上包含了IP+端口。

添加IP端口以及端口和进程之间的连接,属于两个不同主机的进程可以通过TCP(UDP)/IP协议愉快地相互通信(IPC)。

当然,同一主机之间的进程也可以利用这种机制。但是,在同一个主机中还有其他选择,这取决于每个操作系统是否提供相关的机制和支持。TCP/IP是一种广泛使用的标准协议,得到了广泛的支持。

由于篇幅所限,关于这类TCP协议的细节,概念包括套接字、连接、虚拟主机、反向代理等。不会展开。有兴趣的话可以留言,考虑以后写点文章介绍一下。

因为篇幅相同,同时,我也不是计算机网络和协议方面的专家。如果有任何关于端口的缺失或错误,请留言纠正我。端口介绍到此为止。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请发送邮件至 ZLME@xxxxxxxx@hotmail.com 举报,一经查实,立刻删除。

留言与评论(共有 0 条评论)
验证码: