android客户端TCP传输数据、重连、心跳检测

来源:互联网 发布:mac usb是2.0还是3.0 编辑:程序博客网 时间:2024/06/06 16:30

1.Tcp连接、发送数据、接收数据工具类

public class TcpUtil {    public static final int PORT = 9000;    public static final String HOST = "192.168.2.127";    public static Socket socket;    private static TcpUtil utils = null;    public static TcpUtil getInstance(Context context) {        if (utils == null) {            synchronized (TcpUtil.class) {                if (utils == null) {                    utils = new TcpUtil(context);                }            }        }        return utils;    }    PreferencesUtil p;    public TcpUtil(Context context) {        socket = new Socket();        SocketAddress socAddress = new InetSocketAddress(HOST, PORT);        try {            socket.connect(socAddress, 3000);            Log.i("ds>>>", " 連接成功");        } catch (IOException e) {            e.printStackTrace();            if (p == null)                p = new PreferencesUtil(context, "stats");            p.setState(false);            utils = null;            Log.i("ds>>>", " 連接失败");        }    }    /**     * 设置超时时间,该方法必须在bind方法之后使用.     */    public void setSoTimeout(final int timeout) throws Exception {        socket.setSoTimeout(timeout);    }    /**     * 获得超时时间.     */    public int getSoTimeout() throws Exception {        return socket.getSoTimeout();    }    public final Socket getSocket() {        return socket;    }    /**     * 向指定的服务端发送数据信息.     */    public final OutputStream send(final byte[] data) throws IOException {        OutputStream o = null;        if (socket != null)            o = socket.getOutputStream();        if (data != null)            o.write(data);        return o;    }    /**     * 接收从指定的服务端发回的数据.     */    public final boolean receive() throws Exception {        try {            InputStream inputStream = socket.getInputStream();            byte[] b = new byte[1024];            while (true) {                int length = inputStream.read(b);                String Msg = new String(b,0, length,"UTF-8");                if (!StringUtil.isEmpty(Msg))                    return true;            }        } catch (Exception ex) {            ex.printStackTrace();        }        return false;    }    /**     * 关闭tcp连接.     */    public void close() {        try {            socket.close();        } catch (Exception ex) {            ex.printStackTrace();        }    }    public void setNull() {        if (utils != null) utils = null;    }

使用:
由于android中耗时操作(比如网络操作)不能在主线程进行,因此需要开辟新的线程单独做耗时的操作。

new Thread(r).start();
Runnable r = new Runnable() {        @Override        public void run() {            try {                TcpUtil instance = TcpUtil.getInstance(MessageActivity.this);                if (instance != null) {                    instance.send(b5);                    if (instance.receive()) {//客户端发送数据出去后,服务端需返回信息告诉客户端是否接收成功                        runOnUiThread(new Runnable() {                            @Override                            public void run() {                                Toast.makeText(MessageActivity.this, "接收成功", Toast.LENGTH_SHORT).show();                            }                        });                        instance.close();                        returnMsg();                        finish();                    }else {                        runOnUiThread(new Runnable() {                            @Override                            public void run() {                                Toast.makeText(MessageActivity.this, "接收失敗", Toast.LENGTH_SHORT).show();                            }                        });                    }                }            } catch (IOException e) {                if (p == null)                    p = new PreferencesUtil(MessageActivity.this, "stats");                p.setState(false);                e.printStackTrace();            } catch (Exception e) {                e.printStackTrace();            }        }    };
权限相关:<!--允许应用程序改变网络状态-->  <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>  <!--允许应用程序改变WIFI连接状态-->  <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>  <!--允许应用程序访问有关的网络信息-->  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>  <!--允许应用程序访问WIFI网卡的网络信息-->  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>  <!--允许应用程序完全使用网络-->  <uses-permission android:name="android.permission.INTERNET"/>  <uses-permission android:name="android.permission.WAKE_LOCK" /> 

2.Tcp重传、心跳检测

在项目里,我的需求是,a:当软件一运行,就需要告诉服务器,我上线了。b:客户端需求间隔10s发送在线请求判断是否客户端在线。
做法:使用服务!!!每次软件一运行就打开服务,软件关闭关闭服务。

        Intent i = new Intent(MainActivity.this, WorkService.class);        i.setAction("android.intent.action.RESPOND_VIA_MESSAGE");        startService(i);
  <service            android:name=".service.WorkService"            android:label="SmartCamService"            android:enabled="true"            >            <intent-filter>                <action android:name="android.intent.action.RESPOND_VIA_MESSAGE"  />            </intent-filter>        </service>
public class WorkService extends Service {    private byte[] b5;    private PreferencesUtil p;    private int fflag;//fflag=1代表软件第一次打开的请求,fflag=2代表心跳检测。    @Nullable    @Override    public IBinder onBind(Intent intent) {        return null;    }    @Override    public void onCreate() {        super.onCreate();        if (p == null)            p = new PreferencesUtil(getApplication(), "stats");        fflag=1;        Timer timer = new Timer();        timer.schedule(new MyTimerTask(), 0, 10000);    }    @Override    public boolean onUnbind(Intent intent) {        return super.onUnbind(intent);    }    class MyTimerTask extends TimerTask {        public MyTimerTask() {        }        @Override        public void run() {            runResult();        }    }    private void runResult() {        getByteData(fflag);        new Thread(new Runnable() {            @Override            public void run() {                TcpUtil t = TcpUtil.getInstance(getApplication());                if (p == null)                    p = new PreferencesUtil(getApplication(), "stats");                try {                    t.send(b5);                    if (t.receive()) {                        p.setState(true);                        fflag = 2;//只有在成功返回数据时候,才代表是心跳检测步骤了。                    }                } catch (Exception e) {                    p.setState(false);                    fflag=1;//只有一连接失败,fflag就等于1,回到最初软件打开的状态。                    t.setNull();//此时需要有置空操作,这样每次连接失败的时候才能重连。                    e.printStackTrace();                }            }        }).start();    }    private void getByteData(int flag) {//1代表第一次2.代表心跳        JSONObject jsonObject = new JSONObject();        byte[] ECOMMANDTYPE = null;        try {            jsonObject.put("Sn", android.os.Build.SERIAL);            if (flag == 1) jsonObject.put("Name", "");//flag=1或2时候发送给服务器的内容不同            byte[] len = DataUtil.intToBytes(jsonObject.toString().getBytes().length);            byte[] EMESSAGETYPE = DataUtil.intToBytes(2);            if (flag == 1)                ECOMMANDTYPE = DataUtil.intToBytes(0x0100);            else ECOMMANDTYPE = DataUtil.intToBytes(0x0000);//心跳            byte[] Info = jsonObject.toString().getBytes();            byte[] b1 = DataUtil.byteMerger(MyValue.byte_TS_HEAD, len);            byte[] b2 = DataUtil.byteMerger(EMESSAGETYPE, ECOMMANDTYPE);            byte[] b3 = DataUtil.byteMerger(Info, MyValue.byte_TS_TAIL);            byte[] b4 = DataUtil.byteMerger(b1, b2);            b5 = DataUtil.byteMerger(b4, b3);        } catch (JSONException e) {            e.printStackTrace();        }    }}
public class DataUtil {    public static byte[] byteMerger(byte[] byte_1, byte[] byte_2){        byte[] byte_3 = new byte[byte_1.length+byte_2.length];        System.arraycopy(byte_1, 0, byte_3, 0, byte_1.length);        System.arraycopy(byte_2, 0, byte_3, byte_1.length, byte_2.length);        return byte_3;    }    public static byte[] intToBytes( int value )    {        byte[] src = new byte[4];        src[3] =  (byte) ((value>>24) & 0xFF);        src[2] =  (byte) ((value>>16) & 0xFF);        src[1] =  (byte) ((value>>8) & 0xFF);        src[0] =  (byte) (value & 0xFF);        return src;    }}
阅读全文
1 0
原创粉丝点击