前言:将socket开启,发送和接收分开在3个子线程,发送和接收数据互不影响。
1.开启socket子线程
public class StartSocketThread implements Runnable { public static Socket socket; Message msg_main = MainActivity.myhandler.obtainMessage();////////////// @Override public void run() { try { String socket_ip = DeviceMsg.getAddress(); String socket_port = DeviceMsg.getPort(); if (socket_ip==null || socket_port=="") { return; } int Socket_port = Integer.parseInt(socket_port); socket = new Socket(socket_ip,Socket_port);//连接服务端的IP MainActivity.running = true;//socket线程运行中标志位 if(socket.isConnected()&&!socket.isClosed()){//成功连接socket对象 //启动接收数据的线程 new Thread(new SocketReceiveThread(socket)).start(); //启动发送数据的线程 new Thread(new SocketSendThread(socket)).start(); //发送连接成功消息到主线程 msg_main.what=Const.ConnectSuccess; MainActivity.myhandler.sendMessage(msg_main); } }catch (Exception e) { e.printStackTrace(); //利用Handler返回数据(连接失败)到主线程 msg_main.what= Const.ConnectFail; MainActivity.myhandler.sendMessage(msg_main); MainActivity.running = false; Log.e("StartThread:",e.getMessage()); } } }
2. 发送数据子线程
public class SocketSendThread implements Runnable { private OutputStream out = null; public static boolean writing = false; //建立构造函数来获取socket对象的输入流 public SocketSendThread(Socket socket) throws IOException { out = socket.getOutputStream();//得到socket的输出流 } @Override public void run() { // 发送请求数据 while (MainActivity.running) { try { while (writing == true) { writing = false; byte[] codeToSend = CodeList.getCodeToSend(); out.write(codeToSend); String str = new String(codeToSend); } //数据最后加上换行符才可以让服务器端的readline()停止阻塞 // out.write((str).getBytes("utf-8")); } catch (IOException e) { e.printStackTrace(); } } } }
3. 接收数据子线程
public class SocketReceiveThread implements Runnable { private InputStream is; private String str_receive; private String Tag = "SocketReceiveThread"; //建立构造函数来获取socket对象的输入流 public SocketReceiveThread(Socket socket) throws IOException { is = socket.getInputStream(); } @Override public void run() { while (MainActivity.running) { InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); //用Handler把读取到的信息发到主线程 Message msg0 = MainActivity.myhandler.obtainMessage(); try { //读服务器端发来的数据,阻塞直到收到结束符\n或\r // str_receive = br.readLine(); //非阻塞接收数据,但限定接收数据字节 byte buffer[] = new byte[1024*30]; int count = is.read(buffer); if(count != -1){ str_receive = new String(buffer,0,count); } } catch (NullPointerException e) { e.printStackTrace(); Log.e(Tag,e.getMessage()); MainActivity.running = false;//防止服务器端关闭导致客户端读到空指针而导致程序崩溃 msg0.what = Const.ServiceDisconnect; MainActivity.myhandler.sendMessage(msg0);//发送信息通知用户客户端已关闭 break; } catch (IOException e) { e.printStackTrace(); break; } // Message msg0 = MainActivity.myhandler.obtainMessage(); // msg0.what = 1;//把读到的内容更新到UI // msg0.obj = str_receive; // MainActivity.myhandler.sendMessage(msg0); try { Thread.sleep(400); } catch (InterruptedException e) { e.printStackTrace(); Log.e(Tag,e.getMessage()); } } } }
4. socket的使用
public class MainActivity extends BaseActivity { private String Tag = "MainActivity"; public static Handler myhandler; //socket线程是否running的标志位 public static boolean running = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE);//去除标题 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);// 设置全屏 setContentView(R.layout.activity_main); //实例化Handler,用于进程间的通信////////////////// myhandler = new MyHandler(); networkChangeReceiver(); //启动Socket线程 new Thread(new StartSocketThread()).start(); } class MyHandler extends Handler{//在主线程处理Handler传回来的message @Override public void handleMessage(Message msg) { // Intent intent = new Intent("com.example.BroadcastReceiver.MY_BROADCAST"); String currentActivityName = ActivityName.getName(); switch (msg.what) { case 1: String str = (String) msg.obj; Log.i("received:",str); break; case Const.ConnectSuccess: Log.i("handleMessage_Socket", "连接成功"); Toast.makeText(MyApplication.getContext(), "连接成功!", Toast.LENGTH_SHORT).show(); break; case Const.ServiceDisconnect: Log.i("handleMessage_Socket", "服务端连接断开"); Toast.makeText(MyApplication.getContext(), "与服务器断开连接!", Toast.LENGTH_SHORT).show(); break; case Const.ConnectFail: Log.i("handleMessage_Socket", "连接失败"); Toast.makeText(MyApplication.getContext(), "连接失败", Toast.LENGTH_LONG).show(); break; default: break; } } } /** * 销毁activity */ @Override protected void onDestroy(){ super.onDestroy(); if(broadcastReceiver != null){ unregisterReceiver(broadcastReceiver);//取消注册广播 } if (StartSocketThread.socket == null) { return; } try { //关闭Socket线程 this.running = false; StartSocketThread.socket.close(); } catch (NullPointerException | IOException e) { e.printStackTrace(); } } }