参考

1、Android网络编程 - TCP/IP协议实践
2、Android-TCP客户端的实现
3、Android之从TCP/IP、HTTP看Socket通信
4、Android Socket通信--TcpClient
5、WebSocket连接(含重连机制)

截图

1、Android 客户端
Android 基于TCP/IP的Socket通信_第1张图片 image.png
2、PC服务端:用的是SocketTool软件模拟
Android 基于TCP/IP的Socket通信_第2张图片 image.png

流程

1、连接socket的服务端(ip和port):开启异步线程和socket
2、发送数据(OutputStream):异步
3、接收数据(InputStream):注意连接状态,异步读取
4、关闭连接:关闭socket和对应线程

注意

1、异常:android.os.NetworkOnMainThreadException。 socket需要在线程中使用
2、前后端统一传输或者接收协议 [requestcode size d1 d2 d3 ... ],在解析时候用得到
3、实施监控socket的连接状态,还是用心跳包发过去,然后返回数据,一段时间没有的话则代表socket连接失败。

代码

1、TcpClient.java:tcp-socket的客户端,略微做了通用封装,主要是连接,发送,接收,然后设置监听
/** * Created by wujn on 2019/2/15. * Version : v1.0 * Function: tcp client  长度无限制 */public class TcpClient {    /**     * single instance TcpClient     * */    private static TcpClient mSocketClient = null;    private TcpClient(){}    public static TcpClient getInstance(){        if(mSocketClient == null){            synchronized (TcpClient.class) {                mSocketClient = new TcpClient();            }        }        return mSocketClient;    }    String TAG_log = "Socket";    private Socket mSocket;    private OutputStream mOutputStream;    private InputStream mInputStream;    private SocketThread mSocketThread;    private boolean isStop = false;//thread flag    /**     * 128 - 数据按照最长接收,一次性     * */    private class SocketThread extends Thread {        private String ip;        private int port;        public SocketThread(String ip, int port){            this.ip = ip;            this.port = port;        }        @Override        public void run() {            Log.d(TAG_log,"SocketThread start ");            super.run();            //connect ...            try {                if (mSocket != null) {                    mSocket.close();                    mSocket = null;                }                InetAddress ipAddress = InetAddress.getByName(ip);                mSocket = new Socket(ipAddress, port);                //设置不延时发送                //mSocket.setTcpNoDelay(true);                //设置输入输出缓冲流大小                //mSocket.setSendBufferSize(8*1024);                //mSocket.setReceiveBufferSize(8*1024);                if(isConnect()){                    mOutputStream = mSocket.getOutputStream();                    mInputStream = mSocket.getInputStream();                    isStop = false;                    uiHandler.sendEmptyMessage(1);                }                /* 此处这样做没什么意义不大,真正的socket未连接还是靠心跳发送,等待服务端回应比较好,一段时间内未回应,则socket未连接成功 */                else{                    uiHandler.sendEmptyMessage(-1);                    Log.e(TAG_log,"SocketThread connect fail");                    return;                }            }            catch (IOException e) {                uiHandler.sendEmptyMessage(-1);                Log.e(TAG_log,"SocketThread connect io exception = "+e.getMessage());                e.printStackTrace();                return;            }            Log.d(TAG_log,"SocketThread connect over ");            //read ...            while (isConnect() && !isStop && !isInterrupted()) {                int size;                try {                    byte[] buffer = new byte[1024];                    if (mInputStream == null) return;                    size = mInputStream.read(buffer);//null data -1 , zrd serial rule size default 10                    if (size > 0) {                        Message msg = new Message();                        msg.what = 100;                        Bundle bundle = new Bundle();                        bundle.putByteArray("data",buffer);                        bundle.putInt("size",size);                        bundle.putInt("requestCode",requestCode);                        msg.setData(bundle);                        uiHandler.sendMessage(msg);                    }                    Log.i(TAG_log, "SocketThread read listening");                    //Thread.sleep(100);//log eof                }                catch (IOException e) {                    uiHandler.sendEmptyMessage(-1);                    Log.e(TAG_log,"SocketThread read io exception = "+e.getMessage());                    e.printStackTrace();                    return;                }            }        }    }    //==============================socket connect============================    /**     * connect socket in thread     * Exception : android.os.NetworkOnMainThreadException     * */    public void connect(String ip, int port){        mSocketThread = new SocketThread(ip, port);        mSocketThread.start();    }    /**     * socket is connect     * */    public boolean isConnect(){        boolean flag = false;        if (mSocket != null) {            flag = mSocket.isConnected();        }        return flag;    }        /**     * socket disconnect     * */    public void disconnect() {        isStop = true;        try {            if (mOutputStream != null) {                mOutputStream.close();            }            if (mInputStream != null) {                mInputStream.close();            }            if (mSocket != null) {                mSocket.close();                mSocket = null;            }        } catch (IOException e) {            e.printStackTrace();        }        if (mSocketThread != null) {            mSocketThread.interrupt();//not intime destory thread,so need a flag        }    }    /**     * send byte[] cmd     * Exception : android.os.NetworkOnMainThreadException     * */    public void sendByteCmd(final byte[] mBuffer,int requestCode) {        this.requestCode = requestCode;        new Thread(new Runnable() {            @Override            public void run() {                try {                    if (mOutputStream != null) {                        mOutputStream.write(mBuffer);                        mOutputStream.flush();                    }                } catch (IOException e) {                    e.printStackTrace();                }            }        }).start();    }    /**     * send string cmd to serial     */    public void sendStrCmds(String cmd, int requestCode) {        byte[] mBuffer = cmd.getBytes();        sendByteCmd(mBuffer,requestCode);    }    /**     * send prt content cmd to serial     */    public void sendChsPrtCmds(String content, int requestCode) {        try {            byte[] mBuffer = content.getBytes("GB2312");            sendByteCmd(mBuffer,requestCode);        }        catch (UnsupportedEncodingException e1){            e1.printStackTrace();        }    }    Handler uiHandler = new Handler() {        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            switch(msg.what){                //connect error                case -1:                    if (null != onDataReceiveListener) {                        onDataReceiveListener.onConnectFail();                        disconnect();                    }                    break;                //connect success                case 1:                    if (null != onDataReceiveListener) {                        onDataReceiveListener.onConnectSuccess();                    }                    break;                //receive data                case 100:                    Bundle bundle = msg.getData();                    byte[] buffer = bundle.getByteArray("data");                    int size = bundle.getInt("size");                    int mequestCode = bundle.getInt("requestCode");                    if (null != onDataReceiveListener) {                        onDataReceiveListener.onDataReceive(buffer, size, mequestCode);                    }                    break;            }        }    };        /**     * socket response data listener     * */    private OnDataReceiveListener onDataReceiveListener = null;    private int requestCode = -1;    public interface OnDataReceiveListener {        public void onConnectSuccess();        public void onConnectFail();        public void onDataReceive(byte[] buffer, int size, int requestCode);    }    public void setOnDataReceiveListener(            OnDataReceiveListener dataReceiveListener) {        onDataReceiveListener = dataReceiveListener;    }    }
MainActivity.java:使用,简单明了
private void initListener(){        //socket connect        btn_connect.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                String ip = et_ip.getText().toString();                String port = et_port.getText().toString();                if(TextUtils.isEmpty(ip)){                    Toast.makeText(TcpActivity.this,"IP地址为空",Toast.LENGTH_SHORT).show();                    return;                }                if(TextUtils.isEmpty(port)){                    Toast.makeText(TcpActivity.this,"端口号为空",Toast.LENGTH_SHORT).show();                    return;                }                connect(ip, Integer.parseInt(port));            }        });        //socket disconnect        btn_disconnect.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                disconnect();            }        });        //socket send        btn_send.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                if (TcpClient.getInstance().isConnect()) {                    byte[] data = et_send.getText().toString().getBytes();                    send(data);                } else {                    Toast.makeText(TcpActivity.this,"尚未连接,请连接Socket",Toast.LENGTH_SHORT).show();                }            }        });        //clear receive        btn_clear.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                tv_receive.setText("");            }        });    }    /**     * socket data receive     * */    private void initDataReceiver(){        TcpClient.getInstance().setOnDataReceiveListener(dataReceiveListener);    }    /**     * socket connect     * */    private void connect(String ip, int port){        TcpClient.getInstance().connect(ip, port);    }    /**     * socket disconnect     * */    private void disconnect(){        TcpClient.getInstance().disconnect();        tv_state.setText("未连接");    }    /**     * socket send     * */    private void send(byte[] data){        TcpClient.getInstance().sendByteCmd(data,1001);    }    /**     * socket data receive     * data(byte[]) analyze     * */    private TcpClient.OnDataReceiveListener dataReceiveListener = new TcpClient.OnDataReceiveListener() {        @Override        public void onConnectSuccess() {            Log.i(TAG_log,"onDataReceive connect success");            tv_state.setText("已连接");        }        @Override        public void onConnectFail() {            Log.e(TAG_log,"onDataReceive connect fail");            tv_state.setText("未连接");        }        @Override        public void onDataReceive(byte[] buffer, int size, int requestCode) {            //获取有效长度的数据            byte[] data = new byte[size];            System.arraycopy(buffer, 0, data, 0, size);            final String oxValue = Arrays.toString(HexUtil.Byte2Ox(data));            Log.i(TAG_log,"onDataReceive requestCode = "+requestCode + ", content = "+oxValue);            tv_receive.setText(tv_receive.getText().toString() + oxValue + "\n");        }    };    @Override    protected void onDestroy() {        TcpClient.getInstance().disconnect();        super.onDestroy();    }

2019 (* ̄(oo) ̄) 诸事顺利!

更多相关文章

  1. 关于Android中SharedPreferences提交数据效率的调研
  2. Android SQLite数据库应用技巧分享
  3. 使用浏览器查看Android SQLite数据库-Android Debug Database用
  4. Android sql数据库的Android包里面的函数介绍
  5. android根据姓名首字母字符顺序读取通信录
  6. android 使用Intent传递数据之静态变量
  7. android 这篇文章让我更加明白android数据库存储
  8. Android 数据存储之SharedPreferences存储小记

随机推荐

  1. Android下/data/data//files读写权限
  2. 0.[Andriod]之从零安装配置Android Studi
  3. Android 工程报错解决 Unable to resolve
  4. mac os x中android无法连接手机的解决方
  5. Android 设置背景色或者主题。
  6. 【转】Android之大话设计模式与企业级开
  7. ImageButton 和ImageWell 样式的浅析
  8. Android(安卓)Toolbar详解-实现Material
  9. Android EditText 限制输入的字数
  10. Android内核的编译