为啥从Android中的本机程序连接到LocalServerSocket时连接被拒绝
Posted
技术标签:
【中文标题】为啥从Android中的本机程序连接到LocalServerSocket时连接被拒绝【英文标题】:Why Connection refused got when connecting to LocalServerSocket from native program in Android为什么从Android中的本机程序连接到LocalServerSocket时连接被拒绝 【发布时间】:2021-04-02 14:01:05 【问题描述】:有一个 java 服务器 LocalServerSocket 监听一个名为“myaudsocket”的抽象 unix 域套接字,如:
public void listen()
String name = "myaudsocket";
mSocket = new LocalServerSocket(name);
LocalSocket client = mSocket.accept();
...
我可以通过下面的 Java 代码连接服务器:
public void connect()
String name = "myaudsocket";
LocalSocket client = new LocalSocket();
client.connect(new LocalSocketAddress(name));
Log.d("client", "connected to " + name);
但是如果我无法通过本机代码连接到服务器:
#define SOKET_NAME "@myaudsocket"
void connect()
char* name = SOKET_NAME;
struct sockaddr_un addr;
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0)
perror("failed to create socket");
return -1;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, SOKET_NAME, sizeof(addr.sun_path)-1);
if (name[0] == '@')
addr.sun_path[0] = '\0';
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
perror("failed to connect");
close(sock);
return -1;
...
控制台总是说:“连接失败:连接被拒绝”。但是上面的原生代码可以在一般的Linux OS(比如Ubuntu)上运行。
我该如何解决?
【问题讨论】:
为什么将第一个字节设置为 NUL?它是需要为 NUL 的 last 字节。 @user207421 指的是man7.org/linux/man-pages/man7/unix.7.html,据说“抽象:一个抽象套接字地址(与路径名套接字)的区别在于 sun_path[0] 是一个空字节('\ 0')。” 【参考方案1】:问题在于地址长度。从官方参考例子https://man7.org/linux/man-pages/man7/unix.7.html来看,connect()的地址长度参数是sizeof(struct sockaddr_un)
。
它可以在普通的Linux系统(如Ubuntu)下工作。但它不能在android中工作。来自 libcutils 的来源:
https://android-opengrok.bangnimang.net/android-9.0.0_r61/xref/system/core/libcutils/socket_local_client_unix.cpp?r=db87e6d1#111
我们可以看到地址长度设置在结束空字符处,不包括填充零。
*alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
改代码后为:
#define SOKET_NAME "@myaudsocket"
void connect()
char* name = SOKET_NAME;
struct sockaddr_un addr;
// add this variant
int alen;
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0)
perror("failed to create socket");
return -1;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, SOKET_NAME, sizeof(addr.sun_path)-1);
if (name[0] == '@')
addr.sun_path[0] = '\0';
// Added this line
alen = offsetof(struct sockaddr_un, sun_path) + strlen(name);
// change sizeof(addr) to alen
if (connect(sock, (struct sockaddr *)&addr, alen) < 0)
perror("failed to connect");
close(sock);
return -1;
有效。
【讨论】:
以上是关于为啥从Android中的本机程序连接到LocalServerSocket时连接被拒绝的主要内容,如果未能解决你的问题,请参考以下文章
我已经创建了 React 本机应用程序并将其构建为独立的 android apk 文件,但如果不连接到同一网络,我将无法使用它