我正在进行套接字编程。我从下面的链接中获取了参考:
http://examples.javacodegeeks.com/android/core/socket-core/android-socket-example/
以下是有关我的问题的详细信息。我已为此ServerThread创建了Android lib(我的项目要求),这在测试应用程序中使用。
现在测试应用程序通过lib连接到此并执行此过程。第一次它完全正常,但如果我关闭并重新打开,它会因异常而崩溃:
“EADDRINUSE(地址已在使用中)”
还试过serverSocket.setReuseAddress(true)
但没有运气。
我的代码:
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());
}
}
}
如果我呼叫serverSocket.close()
我将收到异常2作为服务器套接字关闭。通信线程与前一个链接中给出的相同。
答案 0 :(得分:25)
在套接字绑定到端口之前,您必须调用setReuseAddress(true)
。您之后正在调用它,因为您正在将端口传递给构造函数,构造函数将立即绑定套接字。
请改为尝试:
serverSocket = new ServerSocket(); // <-- create an unbound socket first
serverSocket.setReuseAddress(true);
serverSocket.bind(new InetSocketAddress(SERVER_PORT)); // <-- now bind it
答案 1 :(得分:8)
TCP(可能还有其他一些)套接字在关闭后的一段时间内无法重用相同的端口。这是为了防止在现有连接的网络上存在数据时出现混淆。您可以覆盖此行为,但默认设置是在允许重用端口之前等待一段时间。
修复此问题的调用是服务器套接字上的setReuseAddress(true)
。但是我不确定它是否需要在第一个套接字或第二个套接字上调用,或者两者都需要。
编辑:
这是一篇博客文章,描述了TCP套接字TIME_WAIT状态及其存在的原因:http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html
答案 2 :(得分:2)
虽然其他答案指出setReuseAddress(true)
的重要性,但可能出现的另一个问题是构造ServerSocket两次并使用相同的参数调用bind。例如,如果您调用问题的代码run()
两次,serverSocket
将被分配给ServerSocket类的新实例,但旧的实例仍然存在,直到收集垃圾。现在使用端口值作为参数构造等于绑定ServerSocket对象,并且最终将绑定到同一地址的两个ServerSocket,这是禁止的异常。所以用你选择的端口只构建一次你的serverSocket!
答案 3 :(得分:0)
尝试在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();
}
}