此篇文章发布距今已超过7天,您需要注意文章的内容或图片是否可用!
烦请楼主告知,知乎提供https://www.zhihu.com服务的服务器进程号(Process ID)是多少?大概率无法告知,因为进程号是操作系统给服务器进程动态分配的(Process ID 0 使用fork创建 ),当前的进程号可能是1949,一旦重启可能就变成2024。而且服务器集群(Cluster)每一个服务器使用的进程号大概率不一样,究竟用哪一个进程号识别应用程序?不需要知道服务器的进程号,照样可以和它通信,因为它使用著名端口号443,准确的说是TCP协议的443端口。浏览器或者APP拿到这个URI= https://www.zhihu.com,立马就解析出Port =443。至于怎么解析,上篇文章有详细介绍。通过端口号来识别应用程序,无论服务器如何重启、无论集群里有多少服务器,只要一个端口号443就可以访问它们,是不是方便多了?!Q2: 网络通信中为何要通过绑定端口号来识别应用程序?通过IANA这个全球组织,将一些端口预留给互联网服务,方便客户端与服务器勾连起来(Socket Pair)。如果把服务器的端口号443、以及IP=1.1.1.1、通过bind命令在Listening_Socket上:Listening_Socket.local_ip =1.1.1.1;Listening_Socket.local_port =443;来自远方的客户端IP= 2.2.2.2,Connect上述的服务器,操作系统分配端口号 =9999,Client_Socket绑定的transport信息如下:Client_Socket.local_ip =2.2.2.2;Client_Socket.local_port =9999;经过大名鼎鼎的TCP三次握手,TCP连接成功建立,则双方的Socket信息update如下:Listening_Socket.local_ip =1.1.1.1;Listening_Socket.local_port =443;Listening_Socket.peer_ip =2.2.2.2;Listening_Socket.peer_port =9999;Client_Socket.local_ip =2.2.2.2;Client_Socket.local_port =9999;Client_Socket.peer_ip =1.1.1.1;Client_Socket.peer_port =443;如果把高亮的服务器Socket比作插座,Client Socket比作插头,一旦Socket Pair(4行信息)配对成功,一个TCP连接就成功建立了。通信双方就可以在Socket Pair上发送(send)、接收(receive)数据了。TCP仅仅是依赖于端口号(local)来识别应用程序的吗?TCP依赖于Local IP + Local Port来识别应用程序的吗?不完全是。仅仅适用于接收Client第一个SYN连接报文。TCP依赖于Local IP + Local Port+ Peer IP + Peer Port来识别应用程序,即上文双方的Socket Pair 各自4行信息。这里的识别程序可以理解为,网卡每秒接收到几百万的Packet,途经TCP的处理之后,将Packet放入 which socket的receive buffer?无论Client还是Server端,依据的是Socket Pair 4元组信息,参照上文的详细描述。通俗地说,Socket Pair 4元组信息,其实就是需要同时满足的4个约束条件的渔网,将属于服务器/客户端的鱼(packet)捞上来,做进一步的处理。再让目光聚焦于“仅仅适用于接收Client第一个SYN连接报文“,什么意思?服务器的Listening Socket仅仅用于TCP连接建立,准确地说,专门用于等待Client的SYN报文的到来,类似于姜太公钓鱼。在Client的SYN报文到达之前,服务器是无法知晓Cient的transport连接信息的(Peer IP + Peer Por)的,Listening_Socket.local_ip =1.1.1.1;Listening_Socket.local_port =443;Listening_Socket.peer_ip =0;Listening_Socket.peer_port =0;故服务器无法使用4个约束条件过滤网捞鱼。而只能使用2个条件捞鱼:Listening_Socket.local_ip =1.1.1.1;Listening_Socket.local_port =443;捞上来的Packet自然由服务器进程处理。服务器一旦接收客户端的SYN,立马就获知了Client的IP、端口号,服务器就有了以下信息:- Listening_Socket.local_ip =1.1.1.1;
- Listening_Socket.local_port =443;
- Listening_Socket.peer_ip =2.2.2.2;
- Listening_Socket.peer_port =9999;
如果服务器真的这么做,那么服务器只能连接一个client(2.2.2.2),来自其它客户端的Packet是无法捞进Listening Socket的。一旦收到client 的SYN报文,按照Listening Socket模板创建一个新的socket, 假设名字为Connected_Socket,则有- Connected_Socket.local_ip =1.1.1.1;
- Connected _Socket.local_port =443;
- Connected _Socket.peer_ip =2.2.2.2;
- Connected _Socket.peer_port =9999;
并fork一个Child Process与这个Connected_Socket关联起来。换句话说,满足该4元组约束条件的packet将交由Child Process处理。而原先的服务器进程继续在Listening Socket继续Listening新的TCP连接请求。- Listening_Socket.local_ip =1.1.1.1;
- Listening_Socket.local_port =443;
- Listening_Socket.peer_ip =0;
- Listening_Socket.peer_port =0;
这里的‘0‘代表wildcard,表示为完全匹配。类似于默认路由的0.0.0.0,匹配所有路由。上文的关键词,Listening Socket与Connected Socket的区别与联系。一个进程号(Process ID)唯一一个进程(Process),一一映射关系。一个进程可以通过socket接口创建任意多个socket,一个socket可以bind一个端口。比较恰当的例子就是http 1.0客户端,一个TCP连接只能用于一次HTTP交易,为了加速下载网页,同时建立多个TCP连接,并行传输http页面。这里是一对多映射关系。对于UDP来说,可以一对一,也可以一对多,一个进程可以创建任意多个Socket,并bind不同的端口号。也可以多对一,即多个进程号映射一个端口号。比如多个进程共同接收特定UDP端口号的组播。对于TCP来说,可以一对一,也可以一对多(参考Q3)。- Client_Socket.local_ip =2.2.2.2;
- Client_Socket.local_port =9999;
- Client_Socket.peer_ip =1.1.1.1;
- Client_Socket.peer_port =443;
- Client_Socket.local_ip =2.2.2.2;
- Client_Socket.local_port =9999;
- Client_Socket.peer_ip =8.8.8.8;
- Client_Socket.peer_port =443;
一个连接1.1.1.1 ,另外一个连接8.8.8.8,即使使用共同的端口号9999,渔网一样可以区分出来。- 如果2个客户端进程让操作系统分配端口号,操作系统会避免使用相同端口号。
- 如果2个客户端进程使用bind强制绑定相同端口号9999,则第一个bind的进程会成功,第二个bind的进程会失败。背后的逻辑是,万一第二个进程连接相同服务器、相同端口号,则2者的4元组则一模一样,无法区分彼此,故拒绝!
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……
宙飒天下网
还没有评论,来说两句吧...