java.net.BindException:绑定失败:EADDRINUSE(地址已在使用中)
Posted
技术标签:
【中文标题】java.net.BindException:绑定失败:EADDRINUSE(地址已在使用中)【英文标题】:java.net.BindException: bind failed: EADDRINUSE (Address already in use) 【发布时间】:2013-12-02 20:07:09 【问题描述】:我有一个服务,它启动 Thread 以在套接字上执行一些操作。代码如下:
public class ServerRunnable implements Runnable
@Override
public void run()
ServerSocket serverSocket = null;
try
serverSocket = new ServerSocket();
serverSocket.setReuseAddress(true);
serverSocket.bind(new InetSocketAddress(ProtocolConstants.USB_SERVER_PORT));
while (true)
Socket client = serverSocket.accept();
// some code
catch (Exception e)
Log.e("Exception while listening on socket.", e);
finally
if (serverSocket != null)
try
serverSocket.close();
catch (IOException e)
Log.e(e);
当我第一次启动服务时,一切正常,但我必须使用stopService
方法停止它。当我再次启动它时,它返回以下异常:
java.net.BindException: bind failed: EADDRINUSE (Address already in use)
此外,我在onDestroy
服务方法中添加了ServerSocket
关闭,但它没有帮助。
setReuseAddress
在bind
之前执行,为什么它不起作用?
【问题讨论】:
我建议您在ServerSocket
实际关闭时登录。要么是你重用了别人的端口,要么是重启时服务实际上并没有完全退出。
【参考方案1】:
据我所知,它卡在serverSocket.accept()
上,等待连接进入。因此,即使关闭应用程序,Runnable 也永远不会完成。再次调用该应用程序会出现此错误(因为该端口仍被之前创建的 Runnable 阻塞)。有多种处理方法:
你可以像这样调用和停止你的 Runnable:
ThreadPoolExecutor threadPoolExecutor = Executors.newSingleThreadExecutor();
Runnable longRunningTask = new Runnable();
Future longRunningTaskFuture = threadPoolExecutor.submit(longRunningTask);
longRunningTaskFuture.cancel(true); //this might not trigger right away
你可以通过调用serversocket.close()
来停止serverSocket.accept()
(这会抛出一个需要处理的SocketException)
我通过从我的 Activity 中的 onClose()
方法向我的 serverSocket 发送数据(字符串)解决了这个问题(可能不是处理这个问题的正确方法):
Socket socket = new Socket();
socket.setReuseAddress(true);
socket.connect((new InetSocketAddress(YOURSETTINGS, HERE);
OutputStream os = socket.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(new String("TIMEOUT"));
oos.close();
os.close();
socket.close();
您可以选择在您的服务器中捕获它,如下所示:
ObjectInputStream objectInputStream = new objectInputStream(serverSocket.getInputStream());
Object object = objectInputStream.readObject();
if (object.getClass().equals(String.class) && ((String) object).equals("TIMEOUT"))
//Here you can do something with the Runnable before it is gone
【讨论】:
OP 中没有提到Executor
。为什么你认为对等体应该序列化字符串“TIMEOUT”是另一个谜。 -1
我找不到 socket.connect,您使用的实际 Socket 类是什么?以上是关于java.net.BindException:绑定失败:EADDRINUSE(地址已在使用中)的主要内容,如果未能解决你的问题,请参考以下文章
收到此错误:java.net.BindException:地址已在使用中:无法绑定
如何修复错误原因:java.net.BindException:地址已在使用:在 Quarkus 中绑定?
线程“main”java.net.BindException中的绑定服务器套接字异常:地址已在使用:JVM_Bind java [重复]
解决mac os x下 tomcat启动报 java.net.BindException: Permission denied <null>:80 错误