修改乘客屏幕发现司机屏幕的方式为轮询连接的方式,当连接成功则进行下一步的通讯
This commit is contained in:
donghongyu
2022-06-16 12:21:27 +08:00
parent 5cd97343a9
commit 7f71d69d4c
8 changed files with 676 additions and 34 deletions

View File

@@ -8,10 +8,17 @@ import com.mogo.telematic.client.NettyTcpClient;
import com.mogo.telematic.client.NsdClient;
import com.mogo.telematic.client.listener.MessageStateListener;
import com.mogo.telematic.client.listener.NettyClientListener;
import com.mogo.telematic.discovery.AbstractDiscoveryTask;
import com.mogo.telematic.discovery.DiscoveryDriverListener;
import com.mogo.telematic.discovery.DiscoveryDriverTask;
import com.mogo.telematic.discovery.bean.HostBean;
import com.mogo.telematic.discovery.bean.NetInfo;
import com.mogo.telematic.server.NSDServer;
import com.mogo.telematic.server.netty.NettyServerListener;
import com.mogo.telematic.server.netty.NettyTcpServer;
import java.util.ArrayList;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
@@ -29,6 +36,12 @@ public class NSDNettyManager {
private Context mContext;
private NettyServerListener mListener;
// 采用轮询的方式查询可连接设备
private AbstractDiscoveryTask mDiscoveryTask;
private long network_ip = 0;
private long network_start = 0;
private long network_end = 0;
private NSDNettyManager() {
}
@@ -191,30 +204,76 @@ public class NSDNettyManager {
* @param context
*/
public void searchAndConnectServer(Context context, String uuid, NettyClientListener listener) {
if (mNsdClient == null) {
mNsdClient = new NsdClient(context, SERVER_NAME, new NsdClient.IServerFound() {
@Override
public void onServerFound(NsdServiceInfo info, int port) {
if (info != null) {
String hostAddress = info.getHost().getHostAddress();
Logger.d(TAG, "NSD查询到指定服务器信息ip为" + hostAddress + ",port为" + port);
//获取到指定的地址进行Netty的连接
connectNettyServer(hostAddress, port, uuid, listener);
// 这里暂时关闭原因是因为BUS上无法透穿虚拟机的网络限制
// if (mNsdClient == null) {
// mNsdClient = new NsdClient(context, SERVER_NAME, new NsdClient.IServerFound() {
// @Override
// public void onServerFound(NsdServiceInfo info, int port) {
// if (info != null) {
// String hostAddress = info.getHost().getHostAddress();
// Logger.d(TAG, "NSD查询到指定服务器信息ip为" + hostAddress + ",port为" + port);
// //获取到指定的地址进行Netty的连接
// connectNettyServer(hostAddress, port, uuid, listener);
//
// if (info.getServiceName().startsWith(SERVER_NAME)) {
// //扫描到以后停止
// mNsdClient.stopServiceDiscovery();
// }
// }
// }
//
// @Override
// public void onServerFail() {
// Logger.d(TAG, "NSD查询失败未找到");
// }
// });
// }
// mNsdClient.startNSDClient();
if (info.getServiceName().startsWith(SERVER_NAME)) {
//扫描到以后停止
mNsdClient.stopServiceDiscovery();
}
}
}
// 启动发现司机屏幕任务
mDiscoveryTask = new DiscoveryDriverTask();
network_ip = NetInfo.getUnsignedLongFromIp("192.168.1.0");
@Override
public void onServerFail() {
}
});
int cidr = 24;
// Detected IP
int shift = (32 - cidr);
if (cidr < 31) {
network_start = (network_ip >> shift << shift) + 1;
network_end = (network_start | ((1 << shift) - 1)) - 1;
} else {
network_start = (network_ip >> shift << shift);
network_end = (network_start | ((1 << shift) - 1));
}
mNsdClient.startNSDClient();
mDiscoveryTask.setNetwork(network_ip, network_start, network_end);
mDiscoveryTask.addDiscoveryDriverListener(new DiscoveryDriverListener() {
@Override
public void onSuccess(ArrayList<HostBean> hostList) {
// 这里返回数据代表了有司机端正在运行,这里遍历集合数据进行连接
if (hostList != null && hostList.size() > 0) {
String hostAddress = "";
for (HostBean hostBean : hostList) {
if (mNettyTcpClient != null && (mNettyTcpClient.isConnecting() || mNettyTcpClient.getConnectStatus())) {
Logger.d(TAG, "当前乘客屏幕已经连接到了ip" + hostAddress + ",port为" + 1088);
return;
}
hostAddress = hostBean.ipAddress;
Logger.d(TAG, "NSD查询到指定服务器信息ip为" + hostAddress + ",port为" + 1088);
//获取到指定的地址进行Netty的连接
connectNettyServer(hostAddress, 1088, uuid, listener);
}
} else {
Logger.d(TAG, "扫描完成,未找到可连接司机屏幕服务");
}
}
@Override
public void onCancel() {
}
});
mDiscoveryTask.execute();
}
private void connectNettyServer(String serverAddress, int port, String sign, NettyClientListener listener) {
@@ -241,6 +300,14 @@ public class NSDNettyManager {
if (!mNettyTcpClient.getConnectStatus()) {
mNettyTcpClient.connect();//连接服务器
// 等待连接进行,当连接成功或者失败后复活继续轮训连接
synchronized (mNettyTcpClient) {
try {
mNettyTcpClient.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} else {
Logger.d(TAG, "Client is connected.");
}
@@ -271,6 +338,7 @@ public class NSDNettyManager {
/**
* 连接指定ip服务端
*
* @param ip
*/
public void connectSpecifiedServer(String ip, int port, String uuid, NettyClientListener listener) {

View File

@@ -263,6 +263,9 @@ public class NettyTcpClient {
Log.w(TAG, "Connection isn't done.");
isConnected = false;
}
synchronized (NettyTcpClient.this) {
NettyTcpClient.this.notifyAll();
}
};
public void disconnect() {

View File

@@ -0,0 +1,82 @@
package com.mogo.telematic.discovery;
import android.os.AsyncTask;
import android.util.Log;
import com.mogo.telematic.discovery.bean.HostBean;
import com.mogo.telematic.discovery.bean.NetInfo;
import java.util.ArrayList;
import java.util.List;
/**
* @author mogoauto
*/
public abstract class AbstractDiscoveryTask extends AsyncTask<Void, HostBean, Void> {
private static final String TAG = "AbstractDiscoveryTask";
protected int hosts_done = 0;
private ArrayList<HostBean> hostList = new ArrayList<>();
private List<DiscoveryDriverListener> mDiscoveryDriverListenerList = new ArrayList<>();
protected long ip;
protected long start = 0;
protected long end = 0;
protected long size = 0;
public void addDiscoveryDriverListener(DiscoveryDriverListener discoveryDriverListener) {
mDiscoveryDriverListenerList.add(discoveryDriverListener);
}
public void removeDiscoveryDriverListener(DiscoveryDriverListener discoveryDriverListener) {
mDiscoveryDriverListenerList.remove(discoveryDriverListener);
}
public void setNetwork(long ip, long start, long end) {
this.ip = ip;
this.start = start;
this.end = end;
Log.d(TAG, "setNetwork: ip=" + NetInfo.getIpFromLongUnsigned(ip)
+ ", start=" + NetInfo.getIpFromLongUnsigned(start)
+ ", end=" + NetInfo.getIpFromLongUnsigned(end)
);
}
@Override
abstract protected Void doInBackground(Void... params);
@Override
protected void onProgressUpdate(HostBean... host) {
Log.d(TAG, "onProgressUpdate: isCancelled=" + isCancelled());
if (hostList != null) {
if (!isCancelled()) {
if (host[0] != null) {
hostList.add(host[0]);
}
}
}
}
@Override
protected void onPostExecute(Void unused) {
Log.d(TAG, "onPostExecute: 完成扫描hostList=" + hostList);
if (mDiscoveryDriverListenerList != null) {
for (DiscoveryDriverListener discoveryDriverListener : mDiscoveryDriverListenerList) {
discoveryDriverListener.onSuccess(hostList);
}
}
}
@Override
protected void onCancelled() {
Log.d(TAG, "onCancelled: 取消扫描");
if (mDiscoveryDriverListenerList != null) {
for (DiscoveryDriverListener discoveryDriverListener : mDiscoveryDriverListenerList) {
discoveryDriverListener.onCancel();
}
}
super.onCancelled();
}
}

View File

@@ -0,0 +1,14 @@
package com.mogo.telematic.discovery;
import com.mogo.telematic.discovery.bean.HostBean;
import java.util.ArrayList;
public interface DiscoveryDriverListener {
/**
* @param hostList
*/
void onSuccess(ArrayList<HostBean> hostList);
void onCancel();
}

View File

@@ -0,0 +1,175 @@
package com.mogo.telematic.discovery;
import android.util.Log;
import com.mogo.telematic.discovery.bean.HostBean;
import com.mogo.telematic.discovery.bean.NetInfo;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* 搜索司机端
*
* @author mogoauto
*/
public class DiscoveryDriverTask extends AbstractDiscoveryTask {
private final String TAG = "DiscoveryDriverTask";
private final static int[] DPORTS = {1088};
private final static int TIMEOUT_SCAN = 3600; // seconds
private final static int TIMEOUT_CONNECT = 800; // seconds
private final static int TIMEOUT_SHUTDOWN = 10; // seconds
private final static int THREADS = 10; //FIXME: Test, plz set in options again ?
private int pt_move = 2; // 1=backward 2=forward
private ExecutorService mPool;
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Void doInBackground(Void... params) {
Log.v(TAG, "start=" + NetInfo.getIpFromLongUnsigned(start) + " (" + start + "), end=" + NetInfo.getIpFromLongUnsigned(end) + " (" + end + "), length=" + size);
mPool = Executors.newFixedThreadPool(THREADS);
if (ip <= end && ip >= start) {
Log.i(TAG, "Back and forth scanning");
// gateway
launch(start);
// hosts
long pt_backward = ip;
long pt_forward = ip + 1;
long size_hosts = size - 1;//主机在扫描范围内,扫描数量-1
for (int i = 0; i < size_hosts; i++) {
if (isCancelled()) {
break;
}
Log.d(TAG, "doInBackground: "
+ " ip=" + NetInfo.getIpFromLongUnsigned(ip)
+ " start=" + NetInfo.getIpFromLongUnsigned(start)
+ " end=" + NetInfo.getIpFromLongUnsigned(end)
+ " pt_backward=" + NetInfo.getIpFromLongUnsigned(pt_backward)
+ " pt_forward=" + NetInfo.getIpFromLongUnsigned(pt_forward)
+ " size_hosts" + size_hosts
);
// Set pointer if of limits
if (pt_backward <= start) {
pt_move = 2;
} else if (pt_forward > end) {
pt_move = 1;
}
// Move back and forth
if (pt_move == 1) {
launch(pt_backward);
pt_backward--;
pt_move = 2;
} else if (pt_move == 2) {
launch(pt_forward);
pt_forward++;
pt_move = 1;
}
}
} else {
Log.i(TAG, "Sequencial scanning");
for (long i = start; i <= end; i++) {
if (isCancelled()) {
break;
}
launch(i);
}
}
mPool.shutdown();
try {
if (!mPool.awaitTermination(TIMEOUT_SCAN, TimeUnit.SECONDS)) {
mPool.shutdownNow();
Log.e(TAG, "Shutting down pool");
if (!mPool.awaitTermination(TIMEOUT_SHUTDOWN, TimeUnit.SECONDS)) {
Log.e(TAG, "Pool did not terminate");
}
}
} catch (InterruptedException e) {
e.printStackTrace();
mPool.shutdownNow();
Thread.currentThread().interrupt();
}
Log.d(TAG, "doInBackground: return null");
return null;
}
@Override
protected void onCancelled() {
if (mPool != null) {
synchronized (mPool) {
mPool.shutdownNow();
Log.d(TAG, "onCancelled: 停止线程");
}
}
super.onCancelled();
}
private void launch(long i) {
if (!mPool.isShutdown()) {
Log.d(TAG, "launch: 子线程:" + NetInfo.getIpFromLongUnsigned(i));
mPool.execute(new CheckRunnable(NetInfo.getIpFromLongUnsigned(i)));
}
}
/**
* 扫描测试线程
*/
private class CheckRunnable implements Runnable {
private String addr;
CheckRunnable(String addr) {
this.addr = addr;
}
@Override
public void run() {
if (isCancelled()) {
publish(null);
return;
}
Log.e(TAG, "run=" + addr + " isCancelled()=" + isCancelled());
// Create host object
final HostBean host = new HostBean();
host.responseTime = TIMEOUT_CONNECT;
host.ipAddress = addr;
Socket s = new Socket();
for (int dport : DPORTS) {
try {
s.bind(null);
s.connect(new InetSocketAddress(addr, dport), TIMEOUT_CONNECT);
Log.i(TAG, "found using TCP connect " + addr + " on port=" + dport);
publish(host);
} catch (IOException | IllegalArgumentException e) {
e.printStackTrace();
} finally {
try {
s.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
private void publish(final HostBean host) {
hosts_done++;
if (host == null) {
publishProgress((HostBean) null);
return;
}
publishProgress(host);
}
}

View File

@@ -0,0 +1,108 @@
package com.mogo.telematic.discovery.bean;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.ArrayList;
import java.util.HashMap;
public class HostBean implements Parcelable {
public static final int TYPE_GATEWAY = 0;
public static final int TYPE_COMPUTER = 1;
public int deviceType = TYPE_COMPUTER;
public int isAlive = 1;
public int position = 0;
public int responseTime = 0; // ms
public String ipAddress = null;
public String hostname = null;
public String hardwareAddress = "00:00:00:00:00:00";
public String nicVendor = "Unknown";
public String os = "Unknown";
public HashMap<Integer, String> services = null;
public HashMap<Integer, String> banners = null;
public ArrayList<Integer> portsOpen = null;
public ArrayList<Integer> portsClosed = null;
public HostBean() {
// New object
}
public HostBean(Parcel in) {
// Object from parcel
readFromParcel(in);
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(deviceType);
dest.writeInt(isAlive);
dest.writeString(ipAddress);
dest.writeString(hostname);
dest.writeString(hardwareAddress);
dest.writeString(nicVendor);
dest.writeString(os);
dest.writeInt(responseTime);
dest.writeInt(position);
dest.writeMap(services);
dest.writeMap(banners);
dest.writeList(portsOpen);
dest.writeList(portsClosed);
}
@SuppressWarnings("unchecked")
private void readFromParcel(Parcel in) {
deviceType = in.readInt();
isAlive = in.readInt();
ipAddress = in.readString();
hostname = in.readString();
hardwareAddress = in.readString();
nicVendor = in.readString();
os = in.readString();
responseTime = in.readInt();
position = in.readInt();
services = in.readHashMap(null);
banners = in.readHashMap(null);
portsOpen = in.readArrayList(Integer.class.getClassLoader());
portsClosed = in.readArrayList(Integer.class.getClassLoader());
}
@SuppressWarnings("unchecked")
public static final Creator CREATOR = new Creator() {
@Override
public HostBean createFromParcel(Parcel in) {
return new HostBean(in);
}
@Override
public HostBean[] newArray(int size) {
return new HostBean[size];
}
};
@Override
public String toString() {
return "HostBean{" +
"deviceType=" + deviceType +
", isAlive=" + isAlive +
", position=" + position +
", responseTime=" + responseTime +
", ipAddress='" + ipAddress + '\'' +
", hostname='" + hostname + '\'' +
", hardwareAddress='" + hardwareAddress + '\'' +
", nicVendor='" + nicVendor + '\'' +
", os='" + os + '\'' +
", services=" + services +
", banners=" + banners +
", portsOpen=" + portsOpen +
", portsClosed=" + portsClosed +
'}';
}
}

View File

@@ -0,0 +1,192 @@
package com.mogo.telematic.discovery.bean;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.SupplicantState;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.telephony.TelephonyManager;
import android.util.Log;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class NetInfo {
private final String TAG = "NetInfo";
private static final int BUF = 8 * 1024;
private static final String CMD_IP = " -f inet addr show %s";
private static final String PTN_IP1 = "\\s*inet [0-9\\.]+\\/([0-9]+) brd [0-9\\.]+ scope global %s$";
private static final String PTN_IP2 = "\\s*inet [0-9\\.]+ peer [0-9\\.]+\\/([0-9]+) scope global %s$"; // FIXME: Merge with PTN_IP1
private static final String PTN_IF = "^%s: ip [0-9\\.]+ mask ([0-9\\.]+) flags.*";
private static final String NOIF = "0";
public static final String NOIP = "0.0.0.0";
public static final String NOMASK = "255.255.255.255";
public static final String NOMAC = "00:00:00:00:00:00";
private Context ctxt;
private WifiInfo info;
public String intf = "eth0";
public String ip = NOIP;
public int cidr = 24;
public int speed = 0;
public String ssid = null;
public String bssid = null;
public String carrier = null;
public String macAddress = NOMAC;
public String netmaskIp = NOMASK;
public String gatewayIp = NOIP;
public NetInfo(final Context ctxt) {
this.ctxt = ctxt;
getWifiInfo();
}
private String getInterfaceFirstIp(NetworkInterface ni) {
if (ni != null) {
for (Enumeration<InetAddress> nis = ni.getInetAddresses(); nis.hasMoreElements(); ) {
InetAddress ia = nis.nextElement();
if (!ia.isLoopbackAddress()) {
if (ia instanceof Inet6Address) {
Log.i(TAG, "IPv6 detected and not supported yet!");
continue;
}
return ia.getHostAddress();
}
}
}
return NOIP;
}
private void getCidr() {
if (netmaskIp != NOMASK) {
cidr = IpToCidr(netmaskIp);
} else {
String match;
// Running ip tools
try {
if ((match = runCommand("/system/xbin/ip", String.format(CMD_IP, intf), String.format(PTN_IP1, intf))) != null) {
cidr = Integer.parseInt(match);
return;
} else if ((match = runCommand("/system/xbin/ip", String.format(CMD_IP, intf), String.format(PTN_IP2, intf))) != null) {
cidr = Integer.parseInt(match);
return;
} else if ((match = runCommand("/system/bin/ifconfig", " " + intf, String.format(PTN_IF, intf))) != null) {
cidr = IpToCidr(match);
return;
} else {
Log.i(TAG, "cannot find cidr, using default /24");
}
} catch (NumberFormatException e) {
Log.i(TAG, e.getMessage() + " -> cannot find cidr, using default /24");
}
}
}
private String runCommand(String path, String cmd, String ptn) {
try {
if (new File(path).exists()) {
String line;
Matcher matcher;
Pattern ptrn = Pattern.compile(ptn);
Process p = Runtime.getRuntime().exec(path + cmd);
BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()), BUF);
while ((line = r.readLine()) != null) {
matcher = ptrn.matcher(line);
if (matcher.matches()) {
return matcher.group(1);
}
}
}
} catch (Exception e) {
Log.e(TAG, "Can't use native command: " + e.getMessage());
return null;
}
return null;
}
public boolean getMobileInfo() {
TelephonyManager tm = (TelephonyManager) ctxt.getSystemService(Context.TELEPHONY_SERVICE);
if (tm != null) {
carrier = tm.getNetworkOperatorName();
}
return false;
}
public boolean getWifiInfo() {
WifiManager wifi = (WifiManager) ctxt.getSystemService(Context.WIFI_SERVICE);
if (wifi != null) {
info = wifi.getConnectionInfo();
// Set wifi variables
speed = info.getLinkSpeed();
ssid = info.getSSID();
bssid = info.getBSSID();
macAddress = info.getMacAddress();
gatewayIp = getIpFromIntSigned(wifi.getDhcpInfo().gateway);
// broadcastIp = getIpFromIntSigned((dhcp.ipAddress & dhcp.netmask)
// | ~dhcp.netmask);
netmaskIp = getIpFromIntSigned(wifi.getDhcpInfo().netmask);
return true;
}
return false;
}
public String getNetIp() {
int shift = (32 - cidr);
int start = ((int) getUnsignedLongFromIp(ip) >> shift << shift);
return getIpFromLongUnsigned((long) start);
}
public SupplicantState getSupplicantState() {
return info.getSupplicantState();
}
public static boolean isConnected(Context ctxt) {
NetworkInfo nfo = ((ConnectivityManager) ctxt
.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
if (nfo != null) {
return nfo.isConnected();
}
return false;
}
public static long getUnsignedLongFromIp(String ip_addr) {
String[] a = ip_addr.split("\\.");
return (Integer.parseInt(a[0]) * 16777216 + Integer.parseInt(a[1]) * 65536
+ Integer.parseInt(a[2]) * 256 + Integer.parseInt(a[3]));
}
public static String getIpFromIntSigned(int ip_int) {
String ip = "";
for (int k = 0; k < 4; k++) {
ip = ip + ((ip_int >> k * 8) & 0xFF) + ".";
}
return ip.substring(0, ip.length() - 1);
}
public static String getIpFromLongUnsigned(long ip_long) {
String ip = "";
for (int k = 3; k > -1; k--) {
ip = ip + ((ip_long >> k * 8) & 0xFF) + ".";
}
return ip.substring(0, ip.length() - 1);
}
private int IpToCidr(String ip) {
double sum = -2;
String[] part = ip.split("\\.");
for (String p : part) {
sum += 256D - Double.parseDouble(p);
}
return 32 - (int) (Math.log(sum) / Math.log(2d));
}
}