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

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

原文链接1
原文链接2

平时我们使用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是不能监听同一个端口的。

两个不同的客户端(一个使用tcp一个用udp)可以连接同一个服务器的同一个端口,但是需要两个不同的服务器进程?我觉得是错的,所以我尝试了一下:
服务器:
    public static void main(String[] args) throws IOException {
        //很明显如下程序在同一个进程

        //udp使用5555端口
        DatagramSocket ds = new DatagramSocket(5555);
        byte[] buf = new byte[1024];
        DatagramPacket dp_receive = new DatagramPacket(buf, 1024);
        ds.receive(dp_receive);
        System.out.println("收到udp消息");
        System.out.println("客户端发送udp端口为" + dp_receive.getPort());

        //tcp使用5555端口
        ServerSocket serverSocket = new ServerSocket(5555);
        Socket socket = serverSocket.accept();
        System.out.println("tcp建立了连接");
        System.out.println("客户端发送tcp端口为" + socket.getPort());

    }

客户端:

public static void main(String[] args) throws IOException, InterruptedException {
    //udp使用12345端口发出udp消息
    DatagramSocket ds = new DatagramSocket(12345);
    String str_send = "Hello";
    InetAddress loc = InetAddress.getLocalHost();
    //udp发送到服务器的5555端口
    DatagramPacket dp_send = new DatagramPacket(str_send.getBytes(), str_send.length(), loc, 5555);
    ds.send(dp_send);
    //tcp使用12345端口发送到服务器的5555端口
    Socket socket = new Socket("127.0.0.1", 5555, null, 12345);
}

服务器输出:

收到udp消息 
客户端发送udp端口为12345 
tcp建立了连接 
客户端发送tcp端口为12345

所以很明显,同个进程也可以通过不同的协议监听同一个端口。
---------------------------------------------------------------------------------------------------

总结

  1. 不同协议可以监听同一个端口(不管是不是在服务器的同个进程)
  2. 某个协议的进程可以监听多个客户端的连接,因为只要五元组不同进程就能分辨。
  3. 从上面的例子可以知道,客户端同个进程也可以在同个端口用不同的协议与客户端建立连接。

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

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

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

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

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

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

  • 6
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值