首页 文章

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

提问于
浏览
4

我对Socket和ServerSocket端口的使用感到困惑 . Oracle's java tutorial about sockets说以下内容:

什么是插座?通常,服务器在特定计算机上运行,并且具有绑定到特定端口号的套接字 . 服务器只是等待,监听套接字以便客户端发出连接请求 . 在客户端:客户端知道运行服务器的计算机的主机名以及服务器正在侦听的端口号 . 要发出连接请求,客户端会尝试与服务器的计算机和端口上的服务器进行会合 . 客户端还需要向服务器标识自己,以便绑定到在此连接期间将使用的本地端口号 . 这通常由系统分配 . 如果一切顺利,服务器将接受连接 . 接受后,服务器获取绑定到同一本地端口的新套接字,并将其远程 endpoints 设置为客户端的地址和端口 . 它需要一个新的套接字,以便它可以继续监听原始套接字以获得连接请求,同时满足连接客户端的需求 . 在客户端,如果接受连接,则成功创建套接字,客户端可以使用套接字与服务器通信 . 客户端和服务器现在可以通过写入或读取其套接字进行通信 .

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

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 ),为什么我创建的套接字无法使用它?

2 回答

  • -1

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

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

  • 1

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

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

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

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

    要么

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

相关问题