Android安卓 TCP Socket通信实现 静态IP设置,ping通也无法TCP连接,路由表,usb网卡和wifi网卡共存等相关问题

Android TCP通信

  • 前言
  • 一、系统端
    • 1.开机启动usb0网卡
    • 2.开机配置静态ip方法
    • 3.补充修改动态IP:
  • 二、PC端
    • 1.善用工具查看状态排除问题
  • 三、Android端
    • 1.确保Android端和usb模块端在同一个局域网
    • 2 注意一下通信细节
  • 四、各种问题命令的思路分析简叙
    • 1.用到的命令
    • 2异常问题可能原因
      • 1.Network is unreachable
      • 2.timeout
  • 附加需求
    • 1.搞个开机执行的脚本
    • 2.在init.rc文件直接添加命令
      • 1.找到文件system/core/rootdir/init.rc
      • 2. 增加rc文件适配的命令
      • 3. 补充个idea,可以将命令写入开机启动的root进程
  • 总结
  • 下载

前言

Android设备连接外置usb网卡模块,Android设备想通过TCP连接usb网卡模块的服务,如何开机启动并设置usb网卡模块静态ip,如何解决ping通但TCP还是连不上等问题如何解决?我想这篇文章可以帮助解决所需要的。

一、系统端

1.开机启动usb0网卡

找到系统配置:frameworks/base/core/res/res/values/config.xml

修改:+    <string translatable="false" name="config_ethernet_iface_regex">eth\\d|usb\\d</string>

2.开机配置静态ip方法

一般网卡ip配置文件是在:"/data/misc/ethernet/ipconfig.txt";但实际没有用户配过,则文件不存在。
所以要先找到文件:frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetConfigStore.java
修改函数:readIpAndProxyConfigurations()

if (networks.size() == 0) {
-            Log.w(TAG, "No Ethernet configuration found. Using default.");
-            return new IpConfiguration(IpAssignment.DHCP, ProxySettings.NONE, null, null);
+                                       
+                       StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration();
+                       InetAddress mIpAddr = NetworkUtils.numericToInetAddress("192.168.62.199");
+                       String[] strs = "255.255.255.0".split("\\.");//mask
+                       int count = 0;
+                       for(String str : strs){
+                               if(str.equals("255")){
+                                       count++;
+                               }
+                       }
+                       int prefixLength = count*8;
+                       LinkAddress mIpAddress = new LinkAddress(mIpAddr,prefixLength);
+                       InetAddress mGateway = NetworkUtils.numericToInetAddress("192.168.62.77");//getway
+                       ArrayList<InetAddress> mDnsServers = new ArrayList<InetAddress>();//DNS
+                       mDnsServers.add(NetworkUtils.numericToInetAddress("6.6.6.6"));//dns1
+                       mDnsServers.add(NetworkUtils.numericToInetAddress("8.8.8.8"));//dns2
+                       
+                       staticIpConfiguration.ipAddress = mIpAddress;
+                       staticIpConfiguration.gateway = mGateway;
+                       staticIpConfiguration.dnsServers.addAll(mDnsServers);
+                       
+                       IpConfiguration default_config = new IpConfiguration(IpAssignment.STATIC, ProxySettings.NONE, st
+                       writeIpAndProxyConfigurations(default_config);
+                       Log.w(TAG, "No Ethernet configuration found. Using default.default_config="+default_config);    
+            return default_config;
         }
         ```


3.补充修改动态IP:

public void setMoveIp(){
try {
//对比STATIC,只需要把StaticIpConfiguration赋值为null
IpConfiguration config = new IpConfiguration(IpConfiguration.IpAssignment.DHCP, IpConfiguration.ProxySettings.NONE, null, ProxyInfo.buildDirectProxy(null,0));
mEthManager.setConfiguration(config);
}catch (Exception e) {
e.printStackTrace();
}
}
<font color=#999AAA >

<hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1">

二、PC端

1.善用工具查看状态排除问题

usb模块一定是有ssh访问端口的,具体ssh电脑端的访问工具很多入putty,xshell,WinScp,个人比较喜欢WinScp工具,可以操作模块路径,导入导出文件都很方便,WinScp如图
Android安卓 TCP Socket通信实现 静态IP设置,ping通也无法TCP连接,路由表,usb网卡和wifi网卡共存等相关问题_第1张图片
PC的网络助手可以调试PC和模块是否能连接来确保模块的服务端口无问题
Android安卓 TCP Socket通信实现 静态IP设置,ping通也无法TCP连接,路由表,usb网卡和wifi网卡共存等相关问题_第2张图片

三、Android端

1.确保Android端和usb模块端在同一个局域网

使用ping命令尝试是否都能ping通对方的ip,确保ping通后,可以开始写Andorid 的 Tcp通信应用了,写之前或借鉴之前,可以先去看看android端关于Tcp Socket通信的步骤详解有助于排查问题理清思路,当然我这里也现成的Demo,
注意一下网络权限:

<uses-permission android:name="android.permission.INTERNET"/>

如图:有源码
Android安卓 TCP Socket通信实现 静态IP设置,ping通也无法TCP连接,路由表,usb网卡和wifi网卡共存等相关问题_第3张图片
无源码:
Android安卓 TCP Socket通信实现 静态IP设置,ping通也无法TCP连接,路由表,usb网卡和wifi网卡共存等相关问题_第4张图片
当然,也另有NDK版的Socket客户端服务端实例代码,可以没有适配好的界面,当然可以结合上面的代码合在一起实现界面和jni的socket

2 注意一下通信细节

客户端读数据是使用readLine(),是个阻塞函数,只有读到回车(\n)才会返回,有些服务不沟通,没加回车符,就很麻烦,需要沟通协商都加最好,也可以尝试其它如available(),read等(’\n’,’\r’ 对应十六进制是 0D 0A)。java发送的话加上 “\r\n” 即可。

四、各种问题命令的思路分析简叙

1.用到的命令

ping命令可以知道ip地址是否在局域网
netstat命令可以知道端口是否在监听或被占用
traceroute命令是跟踪路由
iperf命令是灌包命令,可以直达端口,检测ip的端口是否能连通。对排查很有效
iperf -c 192.168.62.199 -i 1 -p 50700 -t 300
如何数据不连贯,说明TCP是不通的,很可能是路由问题
ifconfig命令是可以查看和配置网口ip已经启动
ifconfig usb0 192.168.62.199 up
ip命令是可以查看路由等状态以及添加自己的路由
添加路由:ip rule add from all fwmark 0x0/0xffff lookup main pref 31999
查看路由:ip rule show

2异常问题可能原因

1.Network is unreachable

这个问题一般就是路由问题了,数据还停留在android端,可以参考链接
网卡共存路由问题

2.timeout

这个超时比较常见,一般都是电脑防火墙原因(如何是和电脑Tcp的话),android一般没有防火墙

附加需求

来到这里,差不多算调通了android和usb网卡模块Tcp通信,但一般这些都要集成进系统,而调外置usb网卡的都需要额外添加路由规则,所以需要自行的 ip命令 写到系统到开机能执行的逻辑去。

1.搞个开机执行的脚本

嗯,一般都是这思路,写个shell脚本或c进程,配置init.rc,修改te等,一般改编译报错和selinux报的avc错后差不多可以实现需求,我也是这么过来的,可能累点,但如果是自己独立实现也蛮有Feel的,也给个参考链接:Android开机启动脚本或进程

2.在init.rc文件直接添加命令

命令这么少,还搞脚本,改编译报错,改配置,耐心不足估计也是很郁闷的,所以送上这个技巧。
步骤:

1.找到文件system/core/rootdir/init.rc

在sys.boot_completed属性节点(开机动画结束)写添加的命令

 on property:sys.boot_completed=1
     bootchart stop
+    ip rule add from all fwmark 0x0/0xffff lookup main pref 31999 
+    ip rule add from all lookup main pref 9000

2. 增加rc文件适配的命令

如果加好1步骤,编译烧录,使用ip rule show看到路由添加成功了如图:
Android安卓 TCP Socket通信实现 静态IP设置,ping通也无法TCP连接,路由表,usb网卡和wifi网卡共存等相关问题_第5张图片
恭喜您,您是Lucky boy/girl,你在前人的树下乘凉了
实际情况是添加的ip路由是没生效的,抓日志都不好使,没错,这时候只能去看rc文件解析命令逻辑了。没错rc文件都是在init.cpp解析运行的,有效的命令是配置了才能识别生效,它有个配置的命令数组BuiltinFunctionMap,在文件:system/core/init/builtins.cpp,添加我们的ip命令

const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
         {"wait",                    {1,     2,    do_wait}},
         {"wait_for_prop",           {2,     2,    do_wait_for_prop}},
         {"write",                   {2,     2,    do_write}},
+        {"ip",                          {2,     kMax,    do_ip}},
     };

do_ip实现:
+static int do_ip(const std::vector<std::string>& args) {
+       std::string res;
+       for(size_t i = 0;i<args.size();++i) {
+          res += args[i];
+          if( i != args.size() ){
+                  res += " ";
+          }
+       }
+       res+='\0';
+       
+       LOG(INFO) << "!!!!! builtins do_ip ip args="<<res.c_str();
+       
+       system(res.c_str());
+
+       LOG(INFO) << "!!!!! builtins do_ip ip end";
+    return 0;
+}

3. 补充个idea,可以将命令写入开机启动的root进程

使用 adb shell ps | findstr root 可以看到系统的root进程,这里以netd进程为例(init进程类似)
找到netd进程的文件:system/netd/server/main.cpp,在main()入口最后添加:

     ALOGI("Netd started in %dms", static_cast<int>(s.timeTaken()));
+       
+       ALOGI("##### system() ip config !!");
+       
+       system("ip rule add from all fwmark 0x0/0xffff lookup main pref 31999");
+    system("ip rule add from all lookup main pref 9000");
 
     IPCThreadState::self()->joinThreadPool();

这里提一下,joinThreadPool(),是阻塞的,切记不要写代码在它之后 !

总结

任何需求都必须动手动脑才能记忆牢靠,化成自己的知识积累,需求过程中也参考了很多博客。有几个链接也分享一下
Android 8.0 Tv 修改以太网ip地址 掩码 网关 DNS及DHCP和静态切换
Android NDK开发之旅39–Linux&Android平台下Socket编程
搬砖不易,欢迎拍砖交流

下载

资源已传在csdn
Android Tcp Socket工具及Android Tcp源码

你可能感兴趣的:(Android,Tcp,技术APK,tcp/ip,android,网络,socket)