我正在阅读Sun的Java教程。我在关于套接字的课程中。简单的线程服务器有以下代码:
import java.net.*;
import java.io.*;
public class KKMultiServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
boolean listening = true;
try {
serverSocket = new ServerSocket(4444);
} catch (IOException e) {
System.err.println("Could not listen on port: 4444.");
System.exit(-1);
}
while (listening)
new KKMultiServerThread(serverSocket.accept()).start();
serverSocket.close();
}
}
据说服务器“继续侦听更多传入连接”。我只是不明白它是如何可能的;行serverSocket.accept()
构造一个新的(客户端)Socket
对象,根据教程“绑定到相同的本地端口并具有其......”。那么,服务器如何与客户端通信并在同一端口上侦听更多传入连接呢?据我所知,如果一个端口用于某些连接,它将被阻止,不能用于更多的事情。
那么我在这里出错了什么?
答案 0 :(得分:2)
好吧,套接字不是基于端口的一对一,它在(地址,端口)元组上是唯一的。连接 - 通信中涉及的一对本地和远程套接字 - 用于将传入数据从端口解复用到正确的套接字,允许一个端口上有多个套接字。 See Wikipedia。换句话说,套接字与端口的关系是N-to-1
答案 1 :(得分:1)
在同一端口上获得多个连接是完全可能的,因为每个TCP连接是(本地主机,本地端口,远程主机,远程端口)元组,只要至少1个不同,连接是不同的并且不会干扰(除了带宽下降)
尝试连接到服务器的客户端通常会获得从当前未使用的OS分配的端口
答案 2 :(得分:1)
听力插座就像商务电话交换机上的接待员一样工作。每个人都拨打开关号码,接待员通过让其他人在另一条线路上处理呼叫来响应交换机线路上的每个来电。尽管接待员一次只能拨打一个电话,但开关线只是非常短暂,因为它仅用于建立连接。
[...] TCP使用包含本地和外部地址的所有四个值对传入段进行解复用:目标IP地址,目标端口号,源IP地址和源端口号。 TCP无法通过仅查看目标端口来确定哪个进程获取传入的段。此外,[给定端口号]的[各种]端点中唯一一个将接收传入连接请求的端点是处于监听状态的端点。 (p255, TCP-IP Illustrated Volume 1 ,W。Richard Stevens)
上述引文中的最后一句是理解的关键。
有趣的是,IP地址和端口的组合并未真正识别套接字。这仅在上下文中是唯一的,其中上下文是特定连接或侦听状态。只有一个侦听器套接字可以绑定到特定的IP /端口组合。
答案 3 :(得分:0)
基于此link
accept方法等待,直到客户端启动并请求此服务器的主机和端口上的连接(在此示例中,服务器在端口4444上的假设机器taranis上运行)。当请求并成功建立连接时,accept方法返回一个新的Socket对象,该对象绑定到同一本地端口,并将其远程地址和远程端口设置为客户端的端口。服务器可以通过这个新的客户端与客户端通信。套接字并继续侦听原始ServerSocket上的客户端连接请求此特定版本的程序不会侦听更多客户端连接请求。
以下是SO讨论,可能会清楚地说明单端口如何处理多个客户端调用Port and Socket SO discussion。
简单来说,大多数网络服务器都在端口8080上侦听,多个客户端将访问相同的端口来访问您的网站。
答案 4 :(得分:0)
简短而甜蜜的答案是该端口被其他程序和进程阻止。只有打开端口的程序现在可以监听它。但它可以在同一端口上收听许多不同的客户端。
当客户端连接时,它会创建一个唯一的套接字。套接字由侦听IP地址和端口(您打开的端口)和呼叫IP地址和端口组成。由于呼叫者的IP地址和端口始终是唯一的,因此每个套接字都是唯一的,并且可供您的侦听器识别。
即使我从同一台机器连接了两次你的程序,我的机器也会为每个连接选择一个新的随机源端口 - 从而确保每次都有一个唯一的套接字。