ServerSocket 代码适用于 PC,不适用于 Android
ServerSocket code works on PC, doesn't work on Android
我有以下接受传入客户端的 ServerSocket 代码:
public class Network {
private Socket socket = null;
private ServerSocket serverSocket = null;
private OutputStream outputStream = null;
private BufferedReader reader = null;
private PrintWriter writer = null;
private boolean firstConnect = true;
private String packet;
private static Thread serverThread = null;
public Network() {
serverThread = new Thread(ServerThread());
serverThread.start();
}
private Runnable ServerThread() {
ServerSocket serverSocket = null;
Socket socket = null;
try {
serverSocket = new ServerSocket(1440);
} catch (Exception e) {
System.out.println("Error: " + e);
}
System.out.println("Listening for packets....");
try {
socket = serverSocket.accept();
} catch (Exception e) {
System.out.println("Error: " + e);
}
while (true) {
try {
socket = serverSocket.accept();
CommunicationThread commThread = new CommunicationThread(socket);
new Thread(commThread).start();
System.out.println("User connected: " + socket.getInetAddress());
} catch (Exception e) {
System.out.println("Error: " + e);
}
}
}
class CommunicationThread implements Runnable {
private Socket clientSocket;
private BufferedReader input;
public CommunicationThread(Socket clientSocket) {
this.clientSocket = clientSocket;
try {
this.input = new BufferedReader(new InputStreamReader(
this.clientSocket.getInputStream()));
} catch (Exception e) {
System.out.println("Error: " + e);
}
}
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
String read = input.readLine();
System.out.println(read);
} catch (Exception e) {
System.out.println("Error: " + e);
}
}
}
}
}
此代码在 PC 上运行良好。但是,当 运行 在 android 设备上时,它从不接受客户端。
我已经查看了以下潜在问题:
- linux 上的最小端口是 1024。我正在使用端口 1440;
- 端口 1440 未被使用。服务器在 PC 上工作正常,只是在 android;
上不行
- 问题不是我的特定设备或 android OS。我用过 Galaxy S4、Galaxy S6 和 Sony Z3 compact,都是从 Android 4.3;
开始的不同 OS 版本
- 我在 AndroidManifest 中添加了 "android.permission.INTERNET";
为什么代码仍然无法在我的 android 设备上运行?
您很可能在创建 ServerSocket
的 catch 块中吞下了 NetworkOnMainThreadException
。然后,您将在接受连接的第二个和第三个 catch 块中吞下大量 NPE。不要过度捕捉会在这里帮助你 ;)
在更大的层面上,Android(默认情况下)不喜欢在应用程序的主线程上执行 I/O。查看 Android 关于 Designing for Responsiveness 的指南。
最好的解决方案可能是创建您自己的单独线程来处理这项工作。 AsyncTask
是一种常见且简单的 Android 范例,您 运行 可以在主线程之外执行工作,但实际上 不会 很好-适合于此:它专为短后台任务而设计,而不是长-运行宁那些像套接字侦听。
看来您 accept
的次数太多了。您调用 accept
,它成功应答了第一个传入连接,然后您什么也不做,开始等待第二个连接,然后再开始任何处理。
由于某些时间或生命周期问题导致打开两个连接,这可能在设备 -> PC 上起作用;我不确定。
在您的客户端代码中使用 192.168.171.18 这是您服务器的本地 ip。使用与服务器正在侦听的端口相同的端口。所以不要使用 public ip.
我有以下接受传入客户端的 ServerSocket 代码:
public class Network {
private Socket socket = null;
private ServerSocket serverSocket = null;
private OutputStream outputStream = null;
private BufferedReader reader = null;
private PrintWriter writer = null;
private boolean firstConnect = true;
private String packet;
private static Thread serverThread = null;
public Network() {
serverThread = new Thread(ServerThread());
serverThread.start();
}
private Runnable ServerThread() {
ServerSocket serverSocket = null;
Socket socket = null;
try {
serverSocket = new ServerSocket(1440);
} catch (Exception e) {
System.out.println("Error: " + e);
}
System.out.println("Listening for packets....");
try {
socket = serverSocket.accept();
} catch (Exception e) {
System.out.println("Error: " + e);
}
while (true) {
try {
socket = serverSocket.accept();
CommunicationThread commThread = new CommunicationThread(socket);
new Thread(commThread).start();
System.out.println("User connected: " + socket.getInetAddress());
} catch (Exception e) {
System.out.println("Error: " + e);
}
}
}
class CommunicationThread implements Runnable {
private Socket clientSocket;
private BufferedReader input;
public CommunicationThread(Socket clientSocket) {
this.clientSocket = clientSocket;
try {
this.input = new BufferedReader(new InputStreamReader(
this.clientSocket.getInputStream()));
} catch (Exception e) {
System.out.println("Error: " + e);
}
}
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
String read = input.readLine();
System.out.println(read);
} catch (Exception e) {
System.out.println("Error: " + e);
}
}
}
}
}
此代码在 PC 上运行良好。但是,当 运行 在 android 设备上时,它从不接受客户端。
我已经查看了以下潜在问题:
- linux 上的最小端口是 1024。我正在使用端口 1440;
- 端口 1440 未被使用。服务器在 PC 上工作正常,只是在 android; 上不行
- 问题不是我的特定设备或 android OS。我用过 Galaxy S4、Galaxy S6 和 Sony Z3 compact,都是从 Android 4.3; 开始的不同 OS 版本
- 我在 AndroidManifest 中添加了 "android.permission.INTERNET";
为什么代码仍然无法在我的 android 设备上运行?
您很可能在创建 ServerSocket
的 catch 块中吞下了 NetworkOnMainThreadException
。然后,您将在接受连接的第二个和第三个 catch 块中吞下大量 NPE。不要过度捕捉会在这里帮助你 ;)
在更大的层面上,Android(默认情况下)不喜欢在应用程序的主线程上执行 I/O。查看 Android 关于 Designing for Responsiveness 的指南。
最好的解决方案可能是创建您自己的单独线程来处理这项工作。 AsyncTask
是一种常见且简单的 Android 范例,您 运行 可以在主线程之外执行工作,但实际上 不会 很好-适合于此:它专为短后台任务而设计,而不是长-运行宁那些像套接字侦听。
看来您 accept
的次数太多了。您调用 accept
,它成功应答了第一个传入连接,然后您什么也不做,开始等待第二个连接,然后再开始任何处理。
由于某些时间或生命周期问题导致打开两个连接,这可能在设备 -> PC 上起作用;我不确定。
在您的客户端代码中使用 192.168.171.18 这是您服务器的本地 ip。使用与服务器正在侦听的端口相同的端口。所以不要使用 public ip.