繁体   English   中英

Java ServerSocket如何在接受客户端后获得绑定到同一本地端口的新套接字?

[英]How does Java ServerSocket get a new socket bound to the same local port after accept the client?

我对Socket和ServerSocket端口的使用感到困惑。 Oracle关于套接字的java教程说明如下:

什么是插座?

通常,服务器在特定计算机上运行,​​并且具有绑定到特定端口号的套接字。 服务器只是等待,监听套接字以便客户端发出连接请求。 在客户端:客户端知道运行服务器的计算机的主机名以及服务器正在侦听的端口号。 要发出连接请求,客户端会尝试与服务器的计算机和端口上的服务器会合。 客户端还需要向服务器标识自己,以便绑定到在此连接期间将使用的本地端口号。 这通常由系统分配。

如果一切顺利,服务器将接受连接。 接受后,服务器获取绑定到同一本地端口的新套接字,并将其远程端点设置为客户端的地址和端口。 它需要一个新的套接字,以便它可以继续监听原始套接字的连接请求,同时满足连接客户端的需求。

在客户端,如果接受连接,则成功创建套接字,客户端可以使用套接字与服务器通信。 客户端和服务器现在可以通过写入或读取其套接字进行通信。

我尝试了以下代码进行测试。 但它引发了一个例外。

try {
    ServerSocket serverSocket = new ServerSocket(8080);

    Socket socket = serverSocket.accept();

    // This prints 8080
    System.out.println("Local port of accepted socket : " + socket.getLocalPort());  

    // But this throws java.net.BindException: Address already in use: JVM_Bind 
    Socket myClientSocket = new Socket("www.google.com", 80, null, 8080);

} catch (Exception e) {
    e.printStackTrace();
}

我的问题很明显。 serverSocket.accept()返回的套接字可以使用相同的本地端口( 8080 ),为什么我创建的套接字不能使用它?

为了简单起见,侦听TCP套接字已经明确绑定到端口,因此您无法将第二个TCP套接字显式绑定到同一端口(除非两个套接字也明确绑定到不同的IP地址,不包括INADDR_ANY)。

接受的套接字不会通过明确的“绑定”过程。 它们自动获取本地IP地址和端口,如果您在没有绑定的情况下连接它,则出站套接字也是如此。

您的服务器和客户端使用相同的本地端口进行通信。 当您创建服务器套接字时,您“说”它必须在8080端口上侦听。 没关系。 任何想要与服务器套接字通信的人都必须使用此类端口。

但是,就在下面你正在创建一个客户端套接字,使用端口80连接谷歌网站(谷歌正在监听该端口),在最后一个参数中,你说这个套接字必须使用本地端口8080来建立连接。 一次只有一个连接可以使用一个端口,这就是为什么你得到java.net.BindException,服务器和客户端连接都使用8080。

我的建议...从套接字客户端构造函数中获取最后两个参数,或者更改本地客户端端口(总是得到一个高数字以避免与其他进程相同的问题):

Socket myClientSocket = new Socket("www.google.com", 80);

要么

Socket myClientSocket = new Socket("www.google.com", 80, null, 58080);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM