android中的socket使用报错NetworkOnMainThreadException
2019-04-12 11:55 雄风狂飙 阅读(788) 评论(0) 收藏 举报1.先简单贴一下服务端代码:
package com.example.myfirstapp2.socketServer; public class AndroidServer { public static void main(String args[]) { SocketServerMain socketServerMain = SocketServerMain.getInstance(); socketServerMain.server(); } }
package com.example.myfirstapp2.socketServer; import java.io.*; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; public class SocketServerMain implements Runnable{ private final int port = 8888; private static SocketServerMain mainHandle = null; private ServerSocket handle = null; private Socket socket = null; SocketServerMain() { handle = getSocketServerInstance(); } public static SocketServerMain getInstance() { if( mainHandle == null ) { mainHandle = new SocketServerMain(); } return mainHandle; } private ServerSocket getSocketServerInstance() { if( null == handle ) { try { InetAddress bindAddr = InetAddress.getByName("127.0.0.1"); //InetAddress bindAddr = InetAddress.getByName("10.0.2.2"); handle = new ServerSocket(port,10,bindAddr); //handle = new ServerSocket(port); } catch (IOException e) { e.printStackTrace(); } } return handle; } private String readString(InputStream input){ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(input)); StringBuffer sb = new StringBuffer(2048); int i = 0; char[] buffer = new char[2048]; try { i = bufferedReader.read(buffer); } catch (IOException e) { e.printStackTrace(); i = -1; } for (int j=0; j < i; j++) { sb.append((char) buffer[j]); } return sb.toString(); } public void server(){ while(true) { try { System.out.println("server accept ..."); socket = handle.accept(); String input = readString(socket.getInputStream()); System.out.println(input); PrintStream output = new PrintStream( socket.getOutputStream()) ; String outputString = "hello world!!"; outputString.getBytes(); output.write(outputString.getBytes(),0,outputString.getBytes().length); socket.close(); } catch (IOException e) { e.printStackTrace(); } } } @Override public void run() { SocketServerMain socketServerMain = SocketServerMain.getInstance(); socketServerMain.server(); } }
2.客户端代码
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /*SocketServerMain socketServerMain = SocketServerMain.getInstance(); Thread serverThread = new Thread(socketServerMain); serverThread.start();*/ button1 = findViewById(R.id.feepolicy); Thread thread = new Thread(){ public void run(){ button1.setOnClickListener(new SocketClientListener()); //SocketClient socketClient = new SocketClient("10.0.2.2",8888); //socketClient.start(); } }; thread.start(); }
package com.example.myfirstapp2.com.example.myfirstapp2.listener; import android.view.View; import com.example.myfirstapp2.SocketClient; import com.example.myfirstapp2.socketServer.SocketServerMain; public class SocketClientListener implements View.OnClickListener { @Override public void onClick(View v) { System.out.println("start socket ..。。。。。。。。。。。。。。。。。。。。。。。."); SocketClient socketClient = new SocketClient("10.0.2.2",8888); socketClient.request(); //SocketClient socketClient = new SocketClient("10.0.2.2",8888); //socketClient.start(); } }
package com.example.myfirstapp2; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.Socket; public class SocketClient implements Runnable { //private String host = "10.0.2.2"; private String host = "127.0.0.1"; private int port = 8888; private Socket socket = null; private BufferedReader input = null; private PrintStream output = null; public SocketClient(String hostStr, int portInt) { if( hostStr != null && hostStr.length() != 0 ) this.host = hostStr; if( portInt != 0 ) this.port = portInt; try { socket = new Socket(host,port); input = new BufferedReader(new InputStreamReader(socket.getInputStream())); output = new PrintStream( socket.getOutputStream() ); } catch (IOException e) { e.printStackTrace(); } } public static void main(String args[]) { SocketClient socketClient = new SocketClient("",0); Thread thread = new Thread(socketClient); thread.start(); } public void send(String outputString) { System.out.println("send ..............."); System.out.println(outputString.getBytes()); System.out.println(outputString.getBytes().length); output.write(outputString.getBytes(),0,outputString.getBytes().length); } public synchronized String read(){ StringBuffer strBuf = new StringBuffer(2048); int i; char[] buffer = new char[2048]; try { i = input.read(buffer); } catch (IOException e) { e.printStackTrace(); i = -1; } for (int j = 0; j < i; j++) { strBuf.append((char) buffer[j]); } return strBuf.toString(); } public void request() { try { send("hello world!"); String out = read(); System.out.println(out); System.out.println("net connection is ok!"); socket.close(); } catch (IOException e) { e.printStackTrace( ); } } @Override public void run() { try { send("hello world!"); String out = read(); System.out.println(out); System.out.println("net connection is ok!"); socket.close(); } catch (IOException e) { e.printStackTrace( ); } } }
3.问题来了:
app跑起来以后,avd就是各种报错,连接不到服务端。我单独讲代码拿出来测试,客户端和服务端的代码均没有问题。
踩过的坑:网上很多人说要进行端口映射,通过telnet localhost 5554【这意味着进入了avd的管理端。5554,是这么来的--在启动android studio的时候,有这么一句,大家注意一下,就是它:Connected to process 22573 on device mydevice3 [emulator-5554]】 ,然后通过 redir add tcp:8888:8888做端口映射,然后就可以连接了。
但是,上述方法无用。而且在我做了端口映射以后,启动服务器端还会报错说端口被占用。
仔细查看报错,原来是:NetworkOnMainThreadException这个错误,
从这个博客https://blog.csdn.net/llixiangjian/article/details/72910557这里搜到了答案,
在代码中增加如下一段就可以强制在主线程内发起联网请求
if (android.os.Build.VERSION.SDK_INT > 9) { StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); }
另一种解决方案,就是新开一个线程,然后再发起联网请求:
Thread thread = new Thread(){ public void run(){SocketClient socketClient = new SocketClient("10.0.2.2",8888); socketClient.request(); } }; thread.start();
如上的写法是没有问题的,但是如下的写法是不行的:
Thread thread = new Thread(){ public void run(){ button1.setOnClickListener(new SocketClientListener()); } }; thread.start();
这说明,即使是新开的线程,在里面也不能在监听器中有联网请求。
浙公网安备 33010602011771号