在我的应用程序中,我使用TCP套接字连接将android设备连接到服务器。 Socket在每台设备上正常工作,除了安装了Android 7+的设备,我收到“Socket is closed”错误。 Nexus 6P和三星s7上出现套接字问题!
我在Service中的Runnable中使用socket,使用:
初始化套接字public class ClientThread implements Runnable {
public void run() {
while (true) {
try {
DataHandler.indicator.set(false);
mRun = true;
if (DataHandler.DOMAIN_IP.contains(":")) {
serverAddr = Inet4Address.getByName(DataHandler.DOMAIN_IP.split(":")[0]);
} else
serverAddr = Inet4Address.getByName(DataHandler.DOMAIN_IP.replace(":3030", ""));
Log.i("Socket", "Connecting");
socket = new Socket(serverAddr, SERVERPORT);
socket.setKeepAlive(true);
socket.setSoLinger(true, 1);
socket.setSoTimeout(30000);
DataHandler.IP_ADDRESS = socket.getLocalAddress().toString().split("/")[1];
DataInputStream dis = new DataInputStream(socket.getInputStream());
connectionDelay = MIN_WAIT;
Log.i("Socket", "Connected");
String serverMessage = "";
byte[] array = new byte[1024];
while (mRun) {
int firstbye = dis.read();
int arraylength = dis.available();
array = new byte[arraylength];
dis.read(array, 0, array.length);
String str = new String(new byte[]{(byte) firstbye});
serverMessage += str + EncodingUtils.getString(array, "UTF-8");
DataHandler.indicator.set(true);
if (firstbye != -1) {
String mstString = new String(serverMessage);
serverMessage = "";
onReceive(NotificationService.this, mstString);
} else { // if (serverMessage.equalsIgnoreCase("")) {
try {
socket.close();
Log.e("Socket", "Disconnect");
socket = null;
stopClient();
} catch (Exception e) {
e.getMessage();
}
serverMessage = null;
DataHandler.indicator.set(false);
continue;
}
}
} catch (UnknownHostException e) {
isNeedtoWrite = true;
} catch (IOException e1) {
isNeedtoWrite = true;
DataHandler.indicator.set(false);
} finally {
try {
socket.close();
DataHandler.indicator.set(false);
Log.e("Socket", "Disconnect");
socket = null;
stopClient();
} catch (Exception e) {
e.getMessage();
}
}
try {
connectionDelay = Math.min(MAX_WAIT, RandomUtils.nextInt(MIN_WAIT, (int) (connectionDelay * BACKOFF_RATE)));
Log.i("SocketSleep", String.valueOf(connectionDelay));
Thread.sleep(connectionDelay);
DataHandler.indicator.set(false);
} catch (InterruptedException e) {
e.getMessage();
}
}
}
}
在代码到达setSoTimeout之前,它会变为异常。
我尝试了一个使用相同Socket逻辑的不同应用程序,并且在启动时它正常工作然后它意外地掉线并且它不再起作用了。我查看了wireshark,这种情况发生了:
有没有人知道问题是什么?
答案 0 :(得分:1)
Bux修复:
由于以前版本的Android中存在错误,系统没有将主线程上的TCP套接字标记为严格模式违规。 Android 7.0修复了这个bug。出现此行为的应用程序现在抛出android.os.NetworkOnMainThreadException。通常,在主线程上执行网络操作是一个坏主意,因为这些操作通常具有导致ANR和jank的高延迟。
并链接到documentation。
答案 1 :(得分:0)
我发现问题是什么......我实际上有一些叫做
的代码socket.getOutputStream().write(GetSendString());
在我的线程之外,由于NetworkOnMainthread错误导致socket断开/崩溃,但我没有正确处理Exception!
答案 2 :(得分:-2)
使用 .read 命令阅读 InputStream 可能会导致问题。 尝试使用 BufferedReader ,类似于 OutputStream :
BufferedReader dis = new BufferedReader(
new InputStreamReader( socket.getInputStream() ));
PrintWriter os_buffer = new PrintWriter(
new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);