android TCP客户端实例

前言:将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();
        }

    }


}


猜你喜欢

转载自blog.csdn.net/amberoot/article/details/79861293