你正在使用的Go版本是什么( go version
)?
$ go version
go version go1.17.6 darwin/amd64
$ gomobile version
v0.0.0-20220414153400-ce6a79cf6a13
注意: gomobile
版本是从 go.mod
文件中提取的。
这个问题在最新版本的发布中是否重现?
我想说是的,我尝试安装 go1.18.1
并在一个终端示例中将 go
别名到那个,但是 gomobile
是构建 aar 的底层 CLI,而那是最新的版本。
你正在使用什么操作系统和处理器架构( go env
)?
go env
输出
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/myUser/Library/Caches/go-build"
GOENV="/Users/myUser/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/myUser/Projects/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/myUser/Projects/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/Users/myUser/sdk/go1.18.1"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/Users/myUser/sdk/go1.18.1/pkg/tool/darwin_amd64"
GOVCS=""
GOVERSION="go1.18.1"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/Users/myUser/Projects/prototypes/tcp-unreachable-repro/gotcp/go.mod"
GOWORK=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/p4/m1jmc9zd4k9f799j_vc_zcwh0000gp/T/go-build2377311140=/tmp/go-build -gno-record-gcc-switches -fno-common"
不确定在谈论Android时 go env
是否相关,但还是包括了。
你做了什么?
我们有一个用Go编写的库,我们通过 gomobile
编译成一个aar并用于我们的Android应用程序。当我们通过Android的 Network request API 在Android 10及更高版本上连接到Wi-Fi网络时,我们无法从Go代码发起TCP连接。
根据Android的 Wi-Fi infrastructure overview
网络请求API:针对需要连接到对等设备的应用,例如配置IoT设备或将文件传输到相机时。在这种情况下,对等设备启动SoftAP,API允许应用引导用户连接到设备。生成的网络不打算提供互联网访问,不能被系统使用,也不能被任何应用(除了配置应用)使用。
问题似乎是操作系统不将Go代码视为应用程序的一部分,但我也不太确定。我们甚至尝试通过 syscall.Socket()
打开一个套接字然后在该套接字上调用 syscall.Connect()
,但它与通过 net.Dial()
一样失败。
如果你通过设置(即不使用Network request API)将手机连接到有问题的Wi-Fi,那么一切都没有问题。
奇怪的是,我们还有一个团队在使用C++和boost,他们也为他们的本地代码生成JNI绑定,但在他们的情况下,使用Network request API可以工作,所以操作系统将该代码识别为应用程序的一部分并允许它们打开套接字。对于Go来说,尽管代码在同一进程中运行( Getpid
在Go代码和原生Android代码中都返回相同的PID),但它却不行。
我已经创建了一个最小复现仓库,你可以在其中观察到行为: https://github.com/myklosbotond/tcp-unreachable-repro 。它仅适用于Android 10及更高版本,并且在测试之前非常重要的是禁用Hive数据。我们在多个Android版本和来自多个品牌的手机上进行了测试,问题在所有情况下都存在。
你期望看到什么?
可以通过绑定到应用程序的Wi-Fi进行网络调用。
你看到了什么?
请求总是以
dial tcp 192.168.0.1:80: connect: network is unreachable
打开TCP套接字失败的方式失败。
3条答案
按热度按时间r8uurelv1#
@hyangah can you give this a look? This looks painful to reproduce, but also bad.
9jyewag02#
问题似乎是与
Connect()
系统调用有关。如果我在 Cgo 中调用connect()
函数,连接会成功,并且可以使用套接字句柄进行进一步的系统调用以读取和写入数据。我为 my fork of the reproduction repo(使用 Android NDK、Go 系统调用和 Go 代码中的 C 调用进行 TCP 连接测试)添加了一些更多的测试用例。
5w9g7ksd3#
我们决定采用@s23b建议的CGo hack,直到gomobile中这个问题得到妥善解决。