【问题标题】:Java Bind Exception - TCP - Address already in use: connectJava 绑定异常 - TCP - 地址已在使用中:连接
【发布时间】:2017-02-28 19:24:07
【问题描述】:

我知道已经有几个类似的问题,但我没有找到适合我的情况的答复。 请考虑一个简单的客户端-服务器应用程序,我必须在其中设置 TCP 连接。

在服务器端,我通过代码等待 TCP 连接:

ServerSocket mySS= new ServerSocket(10000);
Socket mySocket_ServerSide= mySS.accept();                

在客户端我通过代码请求 TCP 连接:

Socket mySocket_ClientSide= new Socket(); 
mySocket_ClientSide.setReuseAddress(true);
mySocket_ClientSide.bind(new InetSocketAddress(5555)); //always using the same port
mySocket_ClientSide.connect(new InetSocketAddress(serverIP,10000), myTimeout);

everythink 第一次工作时,我在 TCP 连接上完成工作(例如文件传输),然后我关闭(在客户端)与服务器的连接,使用:

mySocket_ClientSide.close(); 

几秒钟后,我必须再次连接到服务器,但出现“地址已在使用中:连接”异常。

我假设客户端进程的状态处于 TIME_WAIT,正如我在本网站的几个问题中所读到的那样。但是我不应该因为 setReuseAddress(true) 而再次使用这个端口吗?

出于某些原因我必须始终绑定到同一个端口(在示例中为 5555)。是否有任何解决方案可以让我绑定到同一个端口?我犯了什么错误?

提前谢谢你 福斯托

【问题讨论】:

  • “一些原因”是什么?
  • 出于什么原因?它们会阻止您进行多个连接,甚至是间隔不到两分钟的连续连接。如果这是 netadmin 强加的防火墙约束,请取消它。它不会增加安全性,只会导致巨大的编程问题。注意肯定错误是“地址已在使用中:绑定”?
  • 您好,感谢您的回复。操作系统是Windows。我的应用程序目前是根据固定端口的要求设计的。我必须重新设计它并做一些工作来改变它......但我明白我必须这样做......

标签: java sockets exception tcp


【解决方案1】:

您的问题体现了相互不一致的要求:

  • 您必须使用相同的源端口
  • 您必须在几秒钟内重新连接。

如您所料,您已进入 TIME_WAIT 状态。这是从同一源 IP:端口到同一目标 IP:端口的连续连接之间的强制性两分钟间隔。 TCP 的规则需要这个间隙来保证连接的完整性。

您可以在某些操作系统上减少 TIME_WAIT 时间,但不建议这样做。相反,您应该摆脱始终使用相同端口的要求。这样做没有任何意义,而且还会阻止您并行形成多个连接。

【讨论】:

  • 。首先谢谢你。正如上面其他评论中所写,我必须重新设计它才能不使用相同的端口。至少限制端口范围可能很有用(这样防火墙可以打开有限数量的端口而不是打开所有端口),但我只是看到不存在这样的命令。因此,我现在的想法是,在客户端,通过绑定一个范围内的随机数,如果端口不可用再试一次。我会欣赏您对此的看法...我认为不打开防火墙中的所有端口的问题应该是常见的,或者不是?
  • 您不能将其限制在某个端口范围内。没有用于此的 API。没有理由不允许防火墙中的所有源端口。正如您所发现的,这些规则所完成的只是对应用程序的不可能性或不便。没有任何好处,无论是安全还是其他。
  • 嗨@EJP。有一个用例是重点:STUN。我正在审查根据 Java 1.6 规范进行的实现。到目前为止,我遇到了几个错误,主要是绑定或通过相同的地址和端口连接,需要修改代码,例如soLinger(true, 0) 从那时起(Java 6 到 8)有什么变化吗?这段代码被签署为用户就绪,来自一个有信誉的来源,但是当我测试时它在很多地方都坏了。我反对将服务器环境降级到 1.6 的想法,因为其中的其他应用程序都是 1.8 规范。
  • 另外,我想知道其他实现是如何解决这个问题的?谷歌有几个 STUN 服务器,我认为 Chrome 是一个客户端。
【解决方案2】:

您的服务器只能接受一个连接。您需要在循环中调用 (Server)Socket.accept() 。在建立连接之前,accept() 方法会一直阻塞。

在您的客户端上,您永远不应该将客户端端点绑定到特定端口,除非您有绝对充分的理由这样做。删除这些行:

mySocket_ClientSide.setReuseAddress(true);
mySocket_ClientSide.bind(new InetSocketAddress(5555)); //always using the same port

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-04-12
    • 2015-12-05
    • 2014-04-27
    • 1970-01-01
    • 1970-01-01
    • 2018-04-17
    • 1970-01-01
    • 2015-07-25
    相关资源
    最近更新 更多