Android 如何令 Socket 不遵循IP路由配置规则?

这是一个很令人感兴趣的话题,总有某些特殊需求的时候,我们都希望固定一些 Socket 从某个 Android Network(网卡)出入站点。

但,显然我们都知道使用 bind(fd, ...) 函数是无法令 Socket 真正不遵循路由表规则得,这真是一个令人痛苦与苦涩的事情。

Linux / Windows 上面可以用一些特殊手段,想要那张网卡发报文都是可以的,但 Android 平台上面受限于权限等一些限制,是不可能用这些特殊手段的,Android 上面没有权限连IP路由配置得权限都是没有的。

在这种情况上面,要实现某个 Socket 不走IP路由,那就必须要研究 Google 提供得 Android Framework 实现里面有没有提供相关的函数可以办到,显然有还挺多。

目前的可选方案大约有几种:

1、Network::bindSocket

2、ConnectivityManager::setProcessDefaultNetwork

3、ConnectivityManager::bindProcessToNetwork

但是,我有话要说,方案看上去是挺多的,但它们的作用域只当前进程空间生效,其它进程无效,除非用 sendfd/recvfd 进行文件描述符内核资源共享(但仅关联的子进程)。

Network::bindSocket 是个最好用的方法,它可以细分到每个具体的 Socket 绑定到特定得网卡设备上面出/入网,而不是如 “ConnectivityManager::setProcessDefaultNetwork”、“ConnectivityManager::bindProcessToNetwork” 若非已 bind 则默认以设置的 Network 进行绑定。

2与3方案底层实现是差不多的,只是名字上面有点区别,都是将当前进程与指定得 Network 进行绑定,但可不可以设置未 NULL?答案是可以得,但是设置为NULL则意味着默认会以当前默认网关路由所指示得 Network 进行绑定,比如WIFI没有网络某些 Android 发行版系统会使用 2/3/4/5G 窝蜂移动数据网络,但如果使用 2与3方案那么只要不切换默认网络为 Network 为窝蜂网络就不会导致出/入网络得设备发生变化。

但,必须提醒人们一点,一旦某个 Socket 与网络之间相互关联以后,假设网络断开或者失效是不会导致 Socket 关闭得,但人们必须显示处理来自 Socket 发生的错误提示,例如:EIO、ENETDOWN、ENETUNREACH、ENODEV、ENOENT、ENOTSOCK、EBADF、EHOSTDOWN、EHOSTUNREACH...等等,系统会通知网络应用程序网络断开或类似得错误提示,所以需要注意这个问题。

Datagram Socket(数据报)套接字类型,bind 0.0.0.0,进行报文侦听,但它绑定了一个具体 Network,那么是否可以忽略该 Network 失效的问题?因为理论上是可以无视网卡变化的。

回答是:不可以,不可以,不可以,但凡与 Network 进行绑定以后,但凡 Network 出现问题该 Socket 都被报废,不要只看到系统此时不会关闭 Socket 句柄,就主观认为是允许可以的,这是错的,因为该 Socket 之后是无法向外发送数据,更不能从外收取数据。

你可能感兴趣的:(C/C++,tcp/ip,android,网络)