美文网首页
关于android使用socket(tcp/ip)通讯

关于android使用socket(tcp/ip)通讯

作者: 现在未来_9ff3 | 来源:发表于2020-05-08 15:45 被阅读0次

    最近做项目,用到了socket通讯,这里先使用的是tcp/ip的方式来进行通讯的,至于socket 套接字和tcp的三次握手之类的东西,自己到网上找一下就有,这里只是介绍一下在Android中如何使用tcp方式进行通讯。

    这里只是实现了较简单的功能,并没涉及到复杂的东西。

    1、和后台进行socket连接。需要的是后台的ip地址和端口

    和后台进行连接

    2、设置心跳包,发送命令或字节数组类似

    通过线程池来管理心跳包发送和断线重连

    3、发送文件

    发送assets下的文件,也可以是内存卡下的文件

    4、接收后台发送的消息

    接收后台消息

    整体的代码,这里我为了检测连接的时间和发送文件需要的时间,使用了objectBox的数据库,进行了时间本地存储(addNote),不需要的直接去掉。

    public class DealSocketServiceextends Service {

        private StringTAG ="sun";

        public DealSocketService() {}

        @Override

        public IBinder onBind(Intent intent) {

            return new ClientBinder();

        }

        public class ClientBinderextends Binder {

            private BoxnotesBox;//数据库相关

            private int mHeart_spacetime =5 *1000;//心跳间隔时间

            private BufferedInputStreambis;

            private BufferedOutputStreambos;

            private ReadThreadmReadThread;

            private HandlermHandler =new Handler() {

                @Override

                public void handleMessage(Message msg) {

                    switch (msg.what) {

                        case 66:

                        MyApp.flag =true;

                        Toast.makeText(getApplication(),"连接成功", Toast.LENGTH_SHORT).show();

                        break;

                    }

            }

        };

        private SocketmSocket;

        private ExecutorServicemExecutorService;

        private int tryCount =0;//重试次数

        public void startConnect() {

            notesBox = ObjectBox.get().boxFor(Note.class);

            //在子线程进行网络操作

            // Service也是运行在主线程,千万不要以为Service意思跟后台运行很像,就以为Service运行在后台子线程

              if (mExecutorService ==null) {

                    mExecutorService = Executors.newCachedThreadPool();

            }

            mExecutorService.execute(connectRunnable);

    }

    private RunnableconnectRunnable =new Runnable() {

    @Override

                public void run() {

    try {

    // 建立Socket连接  tryCount == 0 是刚进程序进行连接  == 1 是断线后进行重连的操作

                        if(tryCount ==1||tryCount ==0){

    addNote("开始连接后台");

    }

    mSocket =new Socket();

    mSocket.connect(new InetSocketAddress("192.168.56.1",11001),10);

    bis =new BufferedInputStream(mSocket.getInputStream());

    bos =new BufferedOutputStream(mSocket.getOutputStream());

    // 创建读取服务器心跳的线程

                        mReadThread =new ReadThread();

    mReadThread.start();

    //开启心跳,每隔15秒钟发送一次心跳

                        mHandler.post(mHeartRunnable);

    tryCount =1;

    addNote("后台连接成功");

    mHandler.sendEmptyMessage(66);

    }catch (Exception e) {

    MyApp.flag =false;

    tryCount++;

    e.printStackTrace();

    Log.i(TAG,"Socket连接建立失败,正在尝试第" +tryCount +"次重连");

    mHandler.postDelayed(new Runnable() {

    @Override

                            public void run() {

    mExecutorService.execute(connectRunnable);

    }

    },mHeart_spacetime);

    }

    }

    };

    public class ReadThreadextends Thread {

    @Override

                public void run() {

    int size;

    byte[] buffer =new byte[1024];

    try {

    while ((size =bis.read(buffer)) != -1) {

    //这里是接收的字符串消息,如果是文件,直接指定文件地址,通过写出流进行保存即可

                            String str =new String(buffer,0, size);

    addNote("接收到后台消息=="+ str);

    Log.i(TAG,"我收到来自服务器的消息: " + str);

    //收到消息后,先移除掉之前的断连消息,然后冲设置一个指定时间后执行的断连任务。实际使用中,后台收到心跳包后,会进行回复,如果收到回复,说明连接活着,

    // 反之说明连接已经挂掉,需要重连。由于在发送心跳的地方已经做了重连,这里就不再进行设置重连

                            mHandler.removeCallbacks(disConnectRunnable);

    mHandler.postDelayed(disConnectRunnable,mHeart_spacetime *4);

    }

    }catch (Exception e) {

    e.printStackTrace();

    MyApp.flag =false;

    }

    }

    }

    private RunnablemHeartRunnable =new Runnable() {

    @Override

                public void run() {

    sendHeart();

    }

    };

    /**

    * 这是发送心跳包的方法,单独放到一个线程中去

    */

            private void sendHeart() {

    mExecutorService.execute(new Runnable() {

    @Override

                    public void run() {

    try {

    bos.write("00".getBytes());

    //一定不能忘记这步操作

                            bos.flush();

    //发送成功以后,重新建立一个心跳消息

                            mHandler.postDelayed(mHeartRunnable,mHeart_spacetime);

    Log.i(TAG,"我发送给服务器的消息: 心跳包消息");

    }catch (Exception e) {

    e.printStackTrace();

    MyApp.flag =false;

    Log.i(TAG,"心跳任务发送失败,正在尝试第" +tryCount +"次重连");

    mExecutorService.execute(connectRunnable);

    }

    }

    });

    }

    public void sendData(String content) {

    mExecutorService.execute(new Runnable() {

    @Override

                    public void run() {

    try {

    //在发送数据前,先将之前的心跳包停掉

                            addNote("向后台发送消息");

    mHandler.removeCallbacks(mHeartRunnable);

    bos.write(content.getBytes());

    //一定不能忘记这步操作

                            bos.flush();

    addNote("向后台发送消息成功");

    //发送成功以后,重新建立一个心跳消息

                            mHandler.postDelayed(mHeartRunnable,mHeart_spacetime);

    Log.i(TAG,"我发送给服务器的消息: 字符串消息");

    }catch (Exception e) {

    e.printStackTrace();

    MyApp.flag =false;

    Log.i(TAG,"数据任务发送失败,正在尝试第" +tryCount +"次重连");

    //mExecutorService.schedule(connectRunnable,mHeart_spacetime, TimeUnit.SECONDS);

                            mExecutorService.execute(connectRunnable);

    }

    }

    });

    }

    public void sendFile(String path) {

    mExecutorService.execute(new Runnable() {

    @Override

                    public void run() {

    try {

    addNote("向后台发送文件");

    mHandler.removeCallbacks(mHeartRunnable);

    OutputStream ss =mSocket.getOutputStream();

    InputStream in = getAssets().open("meet.docx");

    //FileInputStream ii = new FileInputStream(new File(path));

                            int size = -1;

    byte[] car =new byte[1024];

    while ((size = in.read(car,0,1024)) != -1) {

    ss.write(car,0, size);

    }

    //一定不能忘记这步操作

                            ss.flush();

    in.close();

    //发送成功以后,重新建立一个心跳消息

                            addNote("向后台发送文件成功");

    mHandler.postDelayed(mHeartRunnable,mHeart_spacetime);

    Log.i(TAG,"我发送给服务器的消息: 文件消息");

    }catch (Exception e) {

    e.printStackTrace();

    MyApp.flag =false;

    Log.i(TAG,"文件任务发送失败,正在尝试第" +tryCount +"次重连");

    //mExecutorService.schedule(connectRunnable,mHeart_spacetime, TimeUnit.SECONDS);

                            mExecutorService.execute(connectRunnable);

    }

    }

    });

    }

    private RunnabledisConnectRunnable =new Runnable() {

    @Override

                public void run() {

    disConnect();

    }

    };

    private void disConnect() {

    mExecutorService.execute(new Runnable() {

    @Override

                    public void run() {

    try {

    Log.i(TAG,"正在执行断连: disConnect");

    //执行Socket断连

                            mHandler.removeCallbacks(mHeartRunnable);

    if (mReadThread !=null) {

    mReadThread.interrupt();

    }

    if (bos !=null) {

    bos.close();

    }

    if (bis !=null) {

    bis.close();

    }

    if (mSocket !=null) {

    mSocket.shutdownInput();

    mSocket.shutdownOutput();

    mSocket.close();

    }

    MyApp.flag =false;

    }catch (Exception e) {

    e.printStackTrace();

    }

    }

    });

    }

    public void destory() {

    disConnect();

    notesBox.removeAll();

    mHandler.removeCallbacksAndMessages(null);

    }

    private void addNote(String ss) {

    DateFormat df = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);

                String comment ="添加时间: " + df.format(new Date());

                Note note =new Note();

                note.setText(ss);

                note.setComment(comment);

                note.setDate(new Date());

                notesBox.put(note);

            }

        }

    }

    相关文章

      网友评论

          本文标题:关于android使用socket(tcp/ip)通讯

          本文链接:https://www.haomeiwen.com/subject/vzufnhtx.html