多个客户端如何同时连接到服务器上的一个端口,比如80?(译)

原文:How do multiple clients connect simultaneously to one port, say 80, on a server? [duplicate]

平时我们使用ServerSocket指定了某个端口(例如8080),然后多个客户端连接上socket之后就都用这个8080端口和服务器端通讯。或者http服务器使用80端口也是和多个浏览器进行连接通讯。为什么可以这样呢?操作系统的进程在同个端口的多个连接是如何进行分辨的?


译文:

我们这里讲Socket连接:

1. 端口只是一个数字辨识,不是真正的物理端口;

2. 一个Socket连接的主键(即不同socket之间的区分)是由一个五元组{SRC-IP, SRC-PORT, DEST-IP, DEST-PORT, PROTOCOL}组成,即{源地址,源端口,目标地址,目标端口,协议}组成,那些说四元组不包含协议的说法是错误的。

3. 一个进程可以拥有多个socket连接。

例子一、两个客户端连接在同个服务器的同个端口80,即有两个socket连接:

- socket1 {SRC-A, 100, DEST-X,80, TCP}

- socket2{SRC-B, 100, DEST-X,80, TCP}

主机A和主机B的地址不同,两台主机同时连接到服务器X的80端口。服务器要怎么处理这个连接是它的事,我们要理解的是为什么一个主机同个端口能监听多个客户端Socket连接。

解释:

1. 是因为两个客户端的IP不同,服务器能识别出不同的Socket;

2. 即使IP地址相同,端口不同,服务器也能够分辨;

3. 只要服务器知道收到的请求和哪个socket相关,那么它就能使用这个socket正确地回复那个客户端;

4. 如果对于不同的socket需要不同的端口,那么不仅仅浪费服务器资源,而且每次客户端连接上serverSocket之后还要另外分配新的端口和客户端通信。没必要。

例子二、不同的进程可以监听同一个端口。

因此在服务器的两个使用不同协议的进程可以监听同一个端口。

如果一个socket的辨识只是四元组不包括协议{SRC-IP, SRC-PORT, DEST-IP, DEST-PORT},那么不同进程是不可能同时监听同一个端口的。没有协议的话一个客户端连接到同一台某个有两个进程监听端口的服务器,那么就没有什么机制可以确定客户端是要连接哪一个进程了。

操作系统(特别是UNIX)中,子进程能够继承父进程的所有文件描述File-descriptors (FD),因此父进程A中监听着的所有socket,也可以被进程的所有子进程A1,A2监听。但是不同进程B是不能监听同一个端口的。


个人理解:

1 问题:多个客户端如何同时连接到服务器上的一个端口,比如80?

答:服务器和不同的客户端进行通信,是通过80端口进行通信的。一个套接字是有五元组的{SRC-IP, SRC-PORT, DEST-IP, DEST-PORT, PROTOCOL},服务端监听80端口号,收到连接请求后,根据客户端的ip和端口号+服务端IP和80端口号创建套接字,然后可以创建一个线程或一个协程通过刚才创建的套接字来和客户端通信。

2 问题:多个客户端同时连接到服务器上的一个端口(比如80),服务器是否会新起另一个端口进行通信?

答:服务器不会新起端口。服务器的80端口一直负责监听客户端的请求,如果有客户端请求,服务器始终使用相同的初试套接字来响应(不需要分配另一个服务器端口),接着创建新的套接字(根据五元组),然后创建一个线程或一个协程通过刚才新创建的套接字来和客户端通信。所以服务器从头到尾只占用了一个80端口进行监听和通信。

3 问题:如果有十万个客户端同时连接服务器,一个80端口是否能容纳这么多客户端连接进行交互?

答:一个80端口是否能容纳和这么多客户端交互,这就是机器性能和程序性能的问题了。



参考:

为什么多个客户端可以连接服务器的同个端口?

原文地址:https://www.cnblogs.com/zkfopen/p/11206612.html

时间: 2024-08-26 06:35:17

多个客户端如何同时连接到服务器上的一个端口,比如80?(译)的相关文章

Android连接socket服务器上传下载多个文件

android连接socket服务器上传下载多个文件1.socket服务端SocketServer.java public class SocketServer { int port = 8888;// 端口号,必须与客户端一致 // 选择进行传输的文件(测试) String path = "C:\\Temp"; String filePath = "E:\\img.png"; Socket client; public static void main(Strin

键入的打印机名不正确,或者指定的打印机没有连接到服务器上

网络打印机不能打印,提示"键入的打印机名不正确,或者指定的打印机没有连接到服务器上" 解决如下: 找到连接打印机的机器(不是通过网络连接),右键单击"我的电脑""管理""服务"将服务"Print Spooler"停止后再启动就可以了.

阿里云服务器上用465端口发送邮件

第一步:安装mailx邮箱服务器 yum -y install mailx 第二步:在mailx配置文件里添加用户名,密码.mailx的配置文件是/etc/mail.rc这个文件. set ssl-verify=ignore ### 启用证书 set nss-config-dir=/root/.certs ### 证书存放的位置 set from="[email protected]" ### 邮箱 set smtp="smtps://smtp.163.com:465&quo

解决不能远程连接Linux服务器上MySQL的问题

今天在实验室的服务器上安装MySQL,装好后却发现远程的电脑无法连接到MySql服务器.服务器操作系统是Ubuntu 14.04.于是在网上查了些资料,折腾了半天后终于搞定了,下面是具体的步骤. 1)安装好MySQL后,修改如下文件 sudo vim /etc/mysql/my.cnf[如果说你不太会用Vi编辑器,你可以用SSH登陆后,将文件移除手动更改后,在上传到服务器覆盖该文件即可] 找到bind-address = 127.0.0.1,将绑定地址改成你服务器的地址[就是你的服务器机器的ip

Hbuilder用ajax连接阿里服务器上的servlet以及注意事项

Hbuiler连接服务器上的servlet的步骤与连接本地项目中的servlet基本一致,详细内容参考上一片博客:https://www.cnblogs.com/ljysy/p/10294640.html 需要将上篇博客中的ajax请求中的ip地址写成自己阿里服务器的相应的ip地址即可 在本片博客中主要是简述一些注意事项 要先在本地测试项目,可以用Hbuider正确访问,然后将本地项目导出一个war包,上传至阿里服务器的tomcat安装目录的webapps目录下(当然,需要事先安装好tomcat

linux系统中启动mysql方式已经客户端如和连接mysql服务器

零点间的记录 一.启动方式1.使用linux命令service 启动:service mysqld start2.使用 mysqld 脚本启动:/etc/inint.d/mysqld start3.使用 safe_mysqld 启动:safe_mysqld& 二.停止1.使用 service 启动:service mysqld stop2.使用 mysqld 脚本启动:/etc/inint.d/mysqld stop3. mysqladmin shutdown 三.重启1.使用 service

spring boot连接linux服务器上的redis

本文章为给新手学习spring boot远程连通redis提供一个学习参考. 环境是intellij idea(window)+ redis(linux虚拟机-vmware). 首先在linux安装好redis,这里网上一堆教程,这里不再赘述. 我用的是centos7,等安装完成ping通之后,接下来开始正题,以下几个步骤帮助你连接redis: 1.修改redis.conf文件(最好拷贝一份,在副本上修改) 注释掉127.0.0.1的限制 把保护模式protected-mode yes 改为 n

如何用navicat连接linux服务器上的mysql

1,开启mysql权限:https://www.cnblogs.com/NaughtyCat/p/how-to-connect-to-mysql-on-linux-by-navicat.html mysql开启root权限(mysql命令下执行) 赋予权限:   grant all privileges on *.* to 'root'@'% 'identified by 'your password' with  grant option 刷新权限列表:   flush privileges

在多个linux服务器上执行一个命令

把服务器的ip地址写到list.txt中 192.168.37.3 192.168.37.4 192.168.37.6 然后运行 for i in `cat list.txt`;do ssh [email protected]$i 'bash commad';done 把user替换成实际登录的用户,'bash command' 替换成实际要执行的命令