Android 套接字 EADDRINUSE(地址已被使用)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24615704/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Socket EADDRINUSE (Address already in use)
提问by morya
I am doing socket programming. I took reference from below link:
我正在做套接字编程。我从以下链接中获取参考:
http://examples.javacodegeeks.com/android/core/socket-core/android-socket-example/
http://examples.javacodegeeks.com/android/core/socket-core/android-socket-example/
Below is detail about my issue. I have created Android lib for this ServerThread (my project requirement), and this is used in test app.
以下是有关我的问题的详细信息。我已经为此 ServerThread 创建了 Android 库(我的项目要求),这用于测试应用程序。
Now test app connect to this through lib and do the process. First time it works perfectly fine, but if I closed and reopen it crashed with exception:
现在测试应用程序通过 lib 连接到它并执行该过程。第一次它工作得很好,但如果我关闭并重新打开它会异常崩溃:
"EADDRINUSE (Address already in use)"
“EADDRINUSE(地址已被使用)”
Also tried serverSocket.setReuseAddress(true)
this but no luck.
也试过serverSocket.setReuseAddress(true)
这个,但没有运气。
My code:
我的代码:
public void run() {
Socket socket = null;
try {
serverSocket = new ServerSocket(SERVER_PORT);
serverSocket.setReuseAddress(true);
} catch (IOException e) {
Log.e(TAG, "exception1= " + e.getMessage());
}
while (!Thread.currentThread().isInterrupted()) {
try {
socket = serverSocket.accept();
Log.d(TAG, "server Connected.......!!!!");
communicationThread = new CommunicationThread(
socket);
commThread = new Thread(communicationThread);
commThread.start();
} catch (IOException e) {
Log.e(TAG, "exception 2=" + e.getMessage());
}
}
}
If I call serverSocket.close()
I am getting exception 2 as server socket close. Communication thread is same as given in previous link.
如果我打电话,serverSocket.close()
我会在服务器套接字关闭时收到异常 2。通信线程与上一个链接中给出的相同。
回答by Remy Lebeau
You have to call setReuseAddress(true)
before the socket is bound to the port. You are calling it after, because you are passing the port to the constructor, which will bind the socket immediately.
您必须setReuseAddress(true)
在套接字绑定到端口之前调用。您在之后调用它,因为您将端口传递给构造函数,它将立即绑定套接字。
Try this instead:
试试这个:
serverSocket = new ServerSocket(); // <-- create an unbound socket first
serverSocket.setReuseAddress(true);
serverSocket.bind(new InetSocketAddress(SERVER_PORT)); // <-- now bind it
回答by Gabe Sechan
TCP (and probably some other) sockets can't reuse the same port for a period after closing. This is to prevent confusion if there's data on the network from an existing connection. You can override this behavior, but the default is to wait for a period of time before allowing reuse of the port.
TCP(可能还有其他一些)套接字在关闭后的一段时间内不能重用相同的端口。如果网络上有来自现有连接的数据,这是为了防止混淆。您可以覆盖此行为,但默认设置是在允许重用端口之前等待一段时间。
The call to fix this is setReuseAddress(true)
on the server socket. But I'm not sure if it needs to be called on the first socket or the second, or both.
解决这个问题的调用是setReuseAddress(true)
在服务器套接字上。但我不确定是否需要在第一个套接字或第二个套接字上调用它,或两者兼而有之。
Edit:
编辑:
Here's a blog post describing the TCP socket TIME_WAIT state and why it exists: http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html
这是一篇描述 TCP 套接字 TIME_WAIT 状态及其存在原因的博客文章:http: //www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable -servers.html
回答by AndrewBloom
While other answers pointed out the importance of setReuseAddress(true)
, another problem that could arise is to construct the ServerSocket twice and call bind with the same parameters. For example if you call twice the code run()
of the question, serverSocket
will be assigned to a new instance of the ServerSocket class, but the old one is still living until garbage collected. Now constructing with the port value as parameter equals to bind the ServerSocket object, and you are going to end up with two ServerSocket bound to the same address, which is forbidden hence the exception. So build your serverSocket with your chosen port only once!
虽然其他答案指出了 的重要性setReuseAddress(true)
,但可能出现的另一个问题是构造 ServerSocket 两次并使用相同的参数调用 bind。例如,如果你调用两次问题的代码run()
,serverSocket
将被分配给ServerSocket 类的一个新实例,但旧的仍然存在,直到垃圾回收。现在用端口值作为参数构造等于绑定 ServerSocket 对象,你最终会得到两个 ServerSocket 绑定到同一个地址,这是禁止的,因此例外。所以只用你选择的端口构建你的 serverSocket 一次!
回答by Marco Aurelio Silva
Try to create the instance of SocketServer outside of the run() method.
尝试在 run() 方法之外创建 SocketServer 的实例。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState)
try {
// create a new instance of an unbound socket first
serverSocket = new ServerSocket();
} catch (IOException e) {
e.printStackTrace();
}
}