android studio安卓手机tcp通信打开app自动连接,连接失败自动重试8次

最近在做一个项目,项目其中一个需求是打开app自动连接tcp服务端,连接失败后自动尝试8次。尝试成功继续,不成功提示服务器未响应。

我想到了用多线程实现,其中一个用于显示尝试状态,另一个线程循环尝试socket=new Socket(),达到以下效果:
在这里插入图片描述

代码如下:

连接tcp用tcp_conn();

 private void tcp_conn(){
        socket=null;
        if(socket!=null) {
            if (socket.isConnected()) {
                system.out.println("已连接");
            }
        }
        else {
            socket = new Socket();
            SocketAddress socAddress = new InetSocketAddress(netAdress, port);
            try {
                socket.connect(socAddress, 1000);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

第一次连接失败后调用ReConnect()

//此线程用于重连尝试,cnt[0]为尝试次数,rctime=8表示最大重连次数
private void ReConnect() {
        new Thread(new Runnable() {
            @Override
            public void run() {
				//因为第一次连接使得socket!=null,所有此处没报错
				//如果socket没有连接,循环尝试,直到连接上或尝试次数达到最大
                while (!socket.isConnected() && cnt[0] < rctime) {
                //调用tcp_conn();
                    tcp_conn();
                    try {
                    //线程延时5秒,等待socket反应,socket连接比较耗时
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //连接成功则跳出循环,cnt[0]=rctime+1为什么要等于它,往下看
                    if (socket.isConnected()) {
                        tv_setText("连接成功");
                        cnt[0] = rctime + 1;//不再重连
                        break;
                    } else {
                    //连接失败,继续尝试
                        cnt[0] += 1;
                        System.out.println("连接失败");
                    }
                }
            }
        }).start();
    }

另一个线程用于打印尝试状态,使用handler定时器,每隔1s检查连接状态,显示到屏幕TextView tv_tip中

//当未连接或尝试次数小于8:tv_tip.setText("连接失败,尝试重新连接:" + cnt[0] + "/" + rctime + "\n");并继续定时
//当尝试次数==8:tv_tip.setText("服务器未响应,请确定服务器已打开");并使cnt[0]=1,继续定时,以便下次进入时关闭定时器
//尝试次数>8:关闭定时器,上面的连接成功后也使cnt[0]>8,以关闭定时器
Handler handler = new Handler();
    final Runnable runnable = new Runnable() {
        @Override
        public void run() {
        //打开一个新的线程
            new Thread(new Runnable() {
                @Override
                public void run() {
                    if (!socket.isConnected() && cnt[0] < rctime) {
                        tv_tip.setText("连接失败,尝试重新连接:" + cnt[0] + "/" + rctime + "\n");
                        handler.postDelayed(runnable, 1000);//每1s执行一次runnable.
                    } else if (cnt[0] == rctime) {
                        cnt[0] += 1;
                        tv_tip.setText("服务器未响应,请确定服务器已打开");
                        handler.postDelayed(runnable, 1000);//每两秒执行一次runnable.
                    } else {
                        handler.removeCallbacks(runnable);
                    }
                }
            }).start();
        }
    };

将所以步骤封装到SystemInit()

private void SystemInit() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                cnt[0] = 0;
                tcp_conn();
                handler.postDelayed(runnable, 1000);//每两秒执行一次runnable.
                if (socket.isConnected()) {
                    {
                        Tip("连接成功", Toast.LENGTH_LONG);
                    }
                } else {
                    ReConnect();
                }
            }
        }).start();
    }

然后在onCreate中调用:

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv_tip = findViewById(R.id.tv_tip);
        SystemInit();
    }

其他布局代码就不贴出来了。
这只是实现了这一步功能,8次之后如果还没连上难道就不行了吗?还要重新打开app才能连?当然可以增加一个刷新按钮,在按钮点击事件中再次调用SystemInit();
所以未连接时要尝试8次,连接成功后跳出ReConnect和关闭定时器。8次后仍未连接放弃尝试,关闭定时器。

验证中,我先在网络调试助手中关闭tcp服务端,打开app,app打印出连接失败,尝试重新连接 2/8,此时我打开tcp服务端,等一会后显示连接成功。如果尝试8次之后还没成功,则显示出“服务器未响应,请确定服务器已打开”。
在这里插入图片描述
在这里插入图片描述
将所有内容封装成类,做了一些改动,UserTcp.java

package com.example.menu_tst;

import android.app.Activity;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.view.Gravity;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.lang.Runnable;
import static android.widget.Toast.LENGTH_LONG;

public class UserTcp extends Activity {
    public Socket socket = null;
    public final TextView tv_tip;
    final int[] cnt = {0};
    public final int rctime = 8;
    private Context context;
    public UserTcp(TextView tv_tip,Context context){
        super();
        this.tv_tip=tv_tip;
        this.context=context;
    }
    public void Tip(String str, int showTime) {
        Looper.prepare();
        Toast toast = Toast.makeText(context, str, showTime);
        toast.setGravity(Gravity.CENTER_HORIZONTAL, 0, 0);  //设置显示位置
        TextView v = (TextView) toast.getView().findViewById(android.R.id.message);
        toast.show();
        Looper.loop();
    }
    public void TcpInit() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                cnt[0] = 0;
                tcp_conn(context);
                handler.postDelayed(runnable, 1000);//每两秒执行一次runnable.
                if (socket.isConnected()) {
                    {
                        Tip("连接成功", LENGTH_LONG);
                    }
                } else {
                    ReConnect(context);
                }
            }
        }).start();
    }


    Handler handler = new Handler();
    final Runnable runnable = new Runnable() {
        @Override
        public void run() {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    if (!socket.isConnected() && cnt[0] < rctime) {
                        System.out.println("连接失败,尝试重新连接:" + cnt[0] + "/" + rctime);
                        //Tip("连接失败,尝试重新连接:" + cnt[0] + "/" + rctime, Toast.LENGTH_LONG);
                        //    tv_tip.setText("连接失败,尝试重新连接:" + cnt[0] + "/" + rctime + "\n");

                        runOnUiThread(new Runnable() {

                            @Override
                            public void run() {
                                tv_tip.setText("连接失败,尝试重新连接:" + cnt[0] + "/" + rctime + "\n");
                            }
                        });


                        handler.postDelayed(runnable, 1000);//每两秒执行一次runnable.
                    } else if (cnt[0] == rctime) {
                        cnt[0] += 1;
                        System.out.println("服务器未响应,请确定服务器已打开");
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                tv_tip.setText("服务器未响应,请确定服务器已打开");
                            }
                        });
                     handler.postDelayed(runnable, 1000);//每两秒执行一次runnable.
                    } else {
                        //Tip("timer",Toast.LENGTH_SHORT);
                        handler.removeCallbacks(runnable);
                    }
                }


            }).start();
        }
    };
    public void ReConnect(Context context) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (!socket.isConnected() && cnt[0] < rctime) {
                    tcp_conn(context);
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (socket.isConnected()) {
                       runOnUiThread(new Runnable() {
                           @Override
                           public void run() {
                               tv_tip.setText("连接成功");
                           }
                       });
                        cnt[0] = rctime + 1;//不再重连
                        break;
                    } else {
                        cnt[0] += 1;
                        System.out.println("连接失败");
                    }
                }
            }
        }).start();
    }

    public void tcp_conn(Context context) {
        socket = null;
        if (socket != null) {
            if (socket.isConnected()) {
                Tip("已连接!!!", Toast.LENGTH_SHORT);
            }
        } else {
            socket = new Socket();
            int port = 6000;
            String netAdress = "192.168.1.7";
            SocketAddress socAddress = new InetSocketAddress(netAdress, port);
            try {
                socket.connect(socAddress, 1000);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if(socket.isConnected()) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        tv_tip.setText("连接成功");
                    }
                });
            }
        }
    }

    public static View getRootView(Context context) {
        Activity activity = (Activity) context;
        return activity.getWindow().getDecorView().findViewById(android.R.id.content);
    }
}

使用时只需调用TcpInit();tv_tip是TextView控件,需自己定义

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值