

监听端口到底是什么意思?
source link: http://dockone.io/article/2434883
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

监听端口到底是什么意思?
这个故事探讨了计算机网络中的一些概念,灵感来自Michael Nielsen的discovery fiction的想法。代码示例也可以在这个repo中找到。截取的片段是在Debian Linux上使用OpenBSD风格的netcat;行为和IPv6的支持可能因版本而异。
在学生会大楼的角落里,有一家咖啡店,在咖啡店的角落里有两个学生。利兹敲打着她哥哥在她搬到大学时给她的那台破旧的手摇MacBook的键盘。在她左边的长椅上,蒂姆在一个装订成卷的笔记本上写着公式。他们之间有一杯半空的常温咖啡,莉兹不时地喝上一口以保持清醒。
在房间的对面,咖啡师把目光从他的手机上移开,抬起头来,扫视着店内的情况。他一个耳朵戴着耳机,另一个悬空,而他的手机正在播放他的电影课的指定观看内容。在这家学生经营的店里,有一条不成文的规定,上夜班的员工可以利用顾客之间的漫长空隙来补习功课。除了蒂姆和丽兹,还有两名男学生独自坐在那里,紧盯着他们的笔记本电脑,他们已经这样做了几个小时。除此之外,店内空无一人。
蒂姆写到一半就停笔了,把这张纸从笔记本上撕下来,揉成一团,放在其他揉成一团的小纸片旁边。
“Shit,现在几点了?”他问到。
利兹看了看她笔记本上的时钟,“刚过两点”
蒂姆打了个哈欠,又开始在新的一页上面涂鸦,但利兹打断了他。
“蒂姆”
“什么?!”,蒂姆回答说,夸张地表达了他对刚开始写就被打断的恼怒。
“在一个端口上监听是什么意思?”
“呃嗯……”
“我必须为net写这个网络服务器的东西”,net是Computer Networks 201的缩写,这是蒂姆在上学期上的一门课。
“是的,我记得那门课”
“所以我在一个端口上监听连接”
“80端口”,蒂姆自信地回答,希望通过抢先回答她的问题来缩短谈话时间。
“实际上,我们应该监听8080,这样它就可以在没有root的情况下运行,但这不是重点。”
“哦,对了。那是什么?”
“好吧,监听一个端口是什么意思?”
“它意味着其他进程可以在该端口上连接到它。”蒂姆对这个问题显得很困惑。
“是的,我知道这一点,但怎么做?”
蒂姆考虑了几秒钟才回答。
“我猜操作系统有一个大的端口表,以及在这些端口上监听的进程。当你绑定到一个端口时,它就会在该表中放一个指向你的套接字的指针。”
“是的,我猜。”利兹说,语气中带着犹豫和不满意。
两人回到了他们各自的工作中。沉默了一段时间后,蒂姆小声嘀咕了一句胜利的 “是的!”,并在一张打印的纸上划掉了一个数字。他终于找到了他在微积分作业中一直纠结的一个证明。
利兹趁机再次引起他的注意。
“嘿,蒂姆,看,我正在同时运行绑定在同一端口的两个进程。”
她调整了两个包含Python代码的窗口的大小。
# server1.py
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('127.0.0.1', 8080))
sock.listen()
print(sock.accept())
然后在它旁边是另一个程序:
# server2.py
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('127.0.0.1', 8080))
print(sock.recv(1024))
然后她向他展示了这两个程序在各自的终端窗口中运行,通过Shell连接到大学的
cslab3
Debian服务器。蒂姆将笔记本电脑转向自己。他打开第三个终端,停顿了一会儿,搜索他疲惫的大脑,然后输入
netcat 127.0.0.1 8080
。netcat
运行后立即退出。在另一个终端窗口中,正在运行的 python server1.py
程序退出,打印。(<socket.socket fd=4, family=AddressFamily.AF_INET,
type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8080),
raddr=('127.0.0.1', 59558)>, ('127.0.0.1', 59558))
他边研究
server1.py
代码,边自言自语。“好的,服务器绑定了一个端口,接受了第一个连接它的套接字,然后退出。我明白了,所以它打印的元组是
accept
调用的结果,然后它立即退出。但是现在......”,将鼠标光标移到显示 server2.py
的编辑器上,“……这一个甚至在听吗?”他在与之前相同的终端中再次运行
netcat 127.0.0.1 8080 -v
,结果打印出来如下:netcat: connect to 127.0.0.1 port 8080 (tcp) failed: Connection refused
“看”,他说,“你的代码中存在一个错误。
server2
仍在运行,但你从未调用listen
。它实际上没有对8080端口做任何事情。”“当然是,看”,利兹说,抢回了她的笔记本电脑。
她在“netcat”命令的末尾加了一个
-u
,然后点击回车。这一次,它没有给出一个错误或立即退出,而是等待键盘输入。她对Tim这么快就认为她的代码有问题感到恼火,她敲出了timmy
,知道这个绰号让他很不爽。netcat
会话无声无息地结束了,同时,python server2.py
程序退出打印。b'timmy\n'
蒂姆意识到利兹试图与他作对,但没有理会,不想让她满足于对他的挑衅。他向键盘做了个手势。利兹把笔记本扭向他的方向,他输入
man netcat'
,调出netcat
的手册,其中描述该工具为“TCP/IP瑞士军刀”。他向下滚动到-u
标志,文件将其简单描述为 “UDP模式”。“啊”,他说,因为他突然想起了什么。“我明白了,server1是通过TCP监听,server2是通过UDP监听。这一定是
SOCK_DGRAM
的意思。所以它们是不同的协议。我猜操作系统为每个端口都有一个单独的表格。我没想到net涵盖了UDP,直到后来。”“是的,我提前读了。”
“当然。你怎么会有时间提前阅读,却没有时间在早晨到期前完成这些作业呢?”
“我也可以问你关于Counter Strike的问题”,莉兹反问道。
蒂姆哼了一声。
他们又继续默默地工作了几分钟,然后莉兹打破了沉默。
“嘿,蒂姆,看看这个。我可以在同一个端口上监听两个进程,即使它们都是TCP。”
蒂姆从他的工作中抬起头来。这次利兹在屏幕上只有一个Python程序,而且是在两个终端中运行:
# server3.py
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
sock.bind(('127.0.0.1', 8080))
sock.listen()
print(sock.accept())
利兹解释说:“看,这个命令显示什么进程正在监听一个端口”。她输入了
lsof -i:8080
,然后点击回车。程序打印:
> lsof -i:8080
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python3 174265 liz 3u IPv4 23850797 0t0 TCP localhost:http-alt (LISTEN)
python3 174337 liz 3u IPv4 23853188 0t0 TCP localhost:http-alt (LISTEN)
“当你连接到它时会发生什么?”,蒂姆问道,这次他的声音中带着一点真正的好奇心。
“看吧。”
利兹运行了一次
netcat localhost 8080
,其中一个服务器进程退出,而另一个则继续运行。然后她再次运行,另一个进程退出。蒂姆的注意力转到了代码上,他把手指放在屏幕附近,读了一遍。莉斯讨厌被弄脏的屏幕,她说:“别紧张!”并把他的手推了回去。“我不会碰它”,他抗议道。他做了一个夸张的表演,让自己的手保持一个安全的距离,他指着
setsockopt
一行,问道:“嘿,这是什么巫术?”“那是设置一个套接字选项,允许端口被重复使用。”
“哼,这在教科书上有吗?”
“不知道,我在Stack Overflow上找到的。”
“我不知道你可以这样重复使用一个端口。”
“我也不知道 "她停顿了一下,考虑了一下。"所以操作系统不能只是有一个端口到套接字的表格,它必须是一个端口到套接字的列表的表格。然后为UDP建立第二个表格。也许还有其他协议的。”
“是的,这听起来很对”,蒂姆同意。
“嗯”,利兹说,突然听起来不太确定。
“什么?”
“呃,没关系”,她说,她开始认真地敲打。
蒂姆回到他的任务上,几分钟后,他又划掉了一个问题。他快要完成了,他的神情也放松了一些。利兹将她的笔记本电脑向他倾斜,说“看看这个”。她给他看了两个程序:
# server4.py
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('127.0.0.2', 8080))
sock.listen()
print(sock.accept())
在它的旁边,
# server5.py
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('127.0.0.3', 8080))
sock.listen()
print(sock.accept())
“这些不是一样的吗?”蒂姆问道,一边研究它们。
“看一下绑定的IP。”
“哦,所以你是在同一个端口上监听,但有两个不同的IP。这能行吗?”
“似乎是的。而且我可以连接到他们两个。”
利兹运行
netcat 127.0.0.2
,然后netcat 127.0.0.3
,给他看。蒂姆思考了一下。“所以让我看看。操作系统必须有一个表,从每个端口和IP组合,到一个套接字。实际上,有两个:一个用于TCP,另一个用于UDP。”
“是的”,利兹点点头。“而不是只有一个套接字,可以是多个。但要注意这个。”她把服务器代码中的IP改为
0.0.0.0
。# server6.py
import socket
sock socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('0.0.0.0', 8080))
sock.listen()
print(sock.accept())
“现在,当我运行绑定到
127.0.0.2
的服务器时,我得到了这个”,她继续说,Traceback (most recent call last):
File "server5.py", line 4, in <module>
s.bind(('127.0.0.2', 8080))
OSError: [Errno 99] Cannot assign requested address
“但是”,她总结道,“如果我运行
netcat 127.0.0.2 8080
,就会连接到0.0.0.0
上的服务器”,并给他看。“对,
0.0.0.0
意味着'绑定所有本地IP',讲课时没有讲到吗?而以127.
开头的地址是本地回环IP,所以它们被它绑定是有道理的。”“是的,但它是如何工作的?大约有1600万个IP是以
127.
开头的。它不会用所有的人做一个大表,对吗?”“我猜不是。”他没有答案,于是改变了话题。“那么无论如何,HTTP服务器的情况如何?”这是个反问句,他知道她没有写过一行实际的任务代码。
“是的,是的”,她回答说,已经潜心于另一个实验。
又过了一段时间。蒂姆刚刚完成他的任务,闲来无事地查看他手机上的时间。他考虑回家去睡他那凹凸不平的宿舍床垫。他评估了一下,觉得长椅也差不多舒服,于是把头向后仰,靠在高高的垫子椅背上。
他正盯着天花板,半梦半醒间,莉兹捅了捅他,说:“蒂姆,看看这个”。
她给他看了另一个程序。
# server7.py
import socket
sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
sock.bind(('::', 8080))
sock.listen()
print(sock.accept())
“看看这个。这是一个IPv6服务器。”
蒂姆打了个哈欠,靠了过来。此时,早晨的阳光已经开始透过他们所坐的长椅后面的窗户出现。另外两个学生在凌晨时分已经悄悄地离开了,店里今天的第一位顾客已经到了,正在等待她的外带咖啡。
“冒号是什么来着?”蒂姆问道。
“这是IPv6中八个零的简称,与IPv4中的
0.0.0.0
含义相同”。“所以这是说要监听所有本地的IPv6 IP?IPv6是这样工作的吗?”
“是的,基本上是这样。”
她输入
netcat "::1" 8080 -v
,解释说:“::1
是IPv6的回环地址。它就像'家'。”“所以就像常规IP中的
127.0.0.1
”“IPv4。是的,没错。但要注意这个。根据
lsof
,我只在IPv6上收听,看到了吗?”利兹运行lsof -i :8080
,打印出一行。COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python3 455017 liz 3u IPv6 25152485 0t0 TCP *:http-alt (LISTEN)
“但是",利兹继续说,“我可以通过一个IPv4的IP连接到它。”
netcat 127.0.0.1 8080 -v
“哼”,蒂姆喃喃道。“那另一种方式呢?你能从一个IPv6 IP连接到一个IPv4服务器吗?”
“不,看这个。”
她运行了
python3 server6.py
,然后netcat "::1" 8080 -v
,打印出了netcat: connect to ::1 port 8080 (tcp) failed: Connection refused
蒂姆问:“如果你试图在IPv6上开始监听8080,而那个IPv4服务器仍在运行,会发生什么?”
利兹给他看,运行
python server7.py
。Traceback (most recent call last):
File "server7.py", line 4, in <module>
s.bind(('::', 8080))
OSError: [Errno 98] Address already in use
“但看看这个”,她说,拉出了另一个代码列表。
# server8.py
import socket
sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1)
sock.bind(('::', 8080))
sock.listen()
print(sock.accept())
她指着
setsockopt
一行,解释说:“当我添加这个时,我可以从不同的进程监听同一端口上的IPv6和IPv4。”她运行
python server8.py
,然后lsof -i :8080
。COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python3 460409 liz 3u IPv6 25188010 0t0 TCP *:http-alt (LISTEN)
python3 460813 liz 3u IPv4 25191765 0t0 TCP *:http-alt (LISTEN)
蒂姆清点了利兹给他看的东西。“所以当你在一个端口上监听时,你实际上是在监听一个端口、一个IP、一个协议、和一个IP版本的组合?”
“是的,除非你在所有的本地IP上监听。如果你在所有IPv6 IP上监听,你也会在所有IPv4 IP上监听,除非你在调用绑定之前特别要求不要这样做。”
“对。因此,操作系统必须有一个从端口和IP对到套接字的哈希图,用于TCP或UDP、IPv4或IPv6的每个组合。”
“到一个套接字的列表”,利兹纠正说。“还记得我是如何监听不止一个的吗?”
“哦,是的。”
“但它还必须处理对所有'家庭'IP的监听,并且能够从一个IPv4 IP上找到一个监听IPv6的套接字。”
“不管怎么说,我得把这个交上去”,蒂姆说着,指了指他手中松散的文件集。"你打算在交稿前完成那个HTTP服务器吗?”
利兹耸耸肩:“我有一个空闲的晚间时间可以利用。”
蒂姆摇了摇头,像极了老父亲般的不赞成。
丽兹翻了个白眼,说:“走吧,蒂姆。”
“下周同一时间?”
“是的。”
原文链接:What does it mean to listen on a port?(翻译:小灰灰)
Recommend
-
8
指定 ASP.NET Core 应用监听的端口 ASP.NET Core 应用默认监听的端口是 5000 , 在调试或者部署的过程中经常需要指定监听的端口来来运行, 本文就这个问题, 进行一个总结, 可以通过下面的方法来指定运行端口。 使用命令行参数
-
2
V2EX › Windows wsl2 手动监听一个端口,但发现打开的却不是这个端口请问是为什么 ysn2233...
-
6
V2EX › C C 语言里面的 inline 关键字到底是啥意思? villivateur · 1 天前 · 2069 次点击
-
4
【跨境词典】Feedback到底是什么意思?跟Review有什么不同?-跨境头条-AMZ123亚马逊导航-跨境电商出海门户 【跨境词典】Feedback到底是什么意思?跟Revi...
-
8
MinMetaspaceExpansion和MaxMetaspaceExpansion这俩个参数到底是什么意思? ...
-
7
比较常见的命令有:netstatlsofps/proc/$pidnetstat# netstat -tuapn参数解释:
-
8
V2EX › Linux win 下 tcp 监听 localhost8000 端口, wsl 内的 ubuntu 如何与之连接? raw0xff
-
4
V2EX › 程序员 chatgpt api 中 temperature 参数到底是什么意思?
-
2
🚀ChatGPT解密:GPT到底是什么意思?有什么用处?✨ https://www.chenweiliang.com/cwl-30492.html 点击上方链接,了解更多关于GPT的神秘世界!🔍 加入我们的探索之旅吧!💫
-
5
监听端口是计算机当前正在使用的端口,用于建立计算机之间的网络连接。虽然打开、监...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK