最近做项目,遇到一个需要通过Localsocket通信的问题,实现Library建立local socket服务端,APK实现Local socket客户端,以前自己也做过,直接在网上找的代码,客户端Java,服务器端C,没有问题。这次客户端还是照着之前的做,服务器端同时做的,然后怎么都连接不上,发现他建立Local socket的方式跟我以前的不一样,然后仔细研究了一下才发现,Local socket的实现方式也分好几种情况。

下面就Android App和Linux中关于Local socket的定义分别介绍。

一 ,Android App中的Local socket

1. Android的LocalSocketAddress

先看看关于LocalSocketAddress的两个构造函数:

/**

* The namespace that this address exists in. See also

* include/cutils/sockets.h ANDROID_SOCKET_NAMESPACE_*

*/

public enum Namespace {

/** A socket in the Linux abstract namespace */

ABSTRACT(0),

/**

* A socket in the Android reserved namespace in /dev/socket.

* Only the init process may create a socket here.

*/

RESERVED(1),

/**

* A socket named with a normal filesystem path.

*/

FILESYSTEM(2);

/** The id matches with a #define in include/cutils/sockets.h */

private int id;

Namespace (int id) {

this.id = id;

}

/**

* @return int constant shared with native code

*/

/*package*/ int getId() {

return id;

}

public LocalSocketAddress(String name, Namespace namespace) {

this.name = name;

this.namespace = namespace;

}

public LocalSocketAddress(String name) {

this(name,Namespace.ABSTRACT);

}

可以看到NameSpace有三种:

ABSTRACT:在系统中维护一个socket描述符,不会在系统上建立文件。

FILESYSTEM:系统会在用户指定的路径下创建一个描述符文件。

RESEVED:系统保留,其本质也是FILESYSTEM,只是文件在/dev/socket/目录下,并且只有init进程才有权限创建

可以看到,如果我们直接用LocalSocketAddress(String name);来指定一个socket的话,那么系统默认它是一个ABSTRACT类型的Local socket。

2.android中socket server端的建立

public LocalServerSocket(String name) throws IOException

{

impl = new LocalSocketImpl();

impl.create(true);

localAddress = new LocalSocketAddress(name);

impl.bind(localAddress);

impl.listen(LISTEN_BACKLOG);

}

/**

* Create a LocalServerSocket from a file descriptor that's already

* been created and bound. listen() will be called immediately on it.

* Used for cases where file descriptors are passed in via environment

* variables

*

* @param fd bound file descriptor

* @throws IOException

*/

public LocalServerSocket(FileDescriptor fd) throws IOException

{

impl = new LocalSocketImpl(fd);

impl.listen(LISTEN_BACKLOG);

localAddress = impl.getSockAddress();

}

我们可以看到,有两种方式建立Local socket的server端,一种是指定名字,这种就对于的是"ABSTRACT"方式,另一中需要指定文件描述符,而且需要实现创建文件描述符并且bound。在网上搜索了一下,没有发现用这种方式创建socket server的,在framework的源码中搜索了一下,发现只有一个地方用到了这个,就是在ZygoteInit.java中。其中createFileDescritor是一个Native的函数,最终调用的是jniCreateFileDescriptor来创建一个文件描述符。在上层socket应用中,一般用不到这种方式。

private static final String ANDROID_SOCKET_ENV = "ANDROID_SOCKET_zygote";

String env = System.getenv(ANDROID_SOCKET_ENV);

fileDesc = Integer.parseInt(env);

sServerSocket = new LocalServerSocket(createFileDescriptor(fileDesc));

3. android中客户端socket的建立

/**

* Creates a AF_LOCAL/UNIX domain stream socket.

*/

public LocalSocket() {

this(new LocalSocketImpl());

isBound = false;

isConnected = false;

}

/**

* Creates a AF_LOCAL/UNIX domain stream socket with FileDescriptor.

* @hide

*/

public LocalSocket(FileDescriptor fd) throws IOException {

this(new LocalSocketImpl(fd));

isBound = true;

isConnected = true;

}

/**

* for use with AndroidServerSocket

* @param impl a SocketImpl

*/

/*package*/ LocalSocket(LocalSocketImpl impl) {

this.impl = impl;

this.isConnected = false;

this.isBound = false;

}

public void connect(LocalSocketAddress endpoint) throws IOException {

synchronized (this) {

if (isConnected) {

throw new IOException("already connected");

}

implCreateIfNeeded();

impl.connect(endpoint, 0);

isConnected = true;

isBound = true;

}

}

LocalSocket有三种构造函数,通常我们用无参数的构造函数,然后用connect中的LocalSocketAddress来指定需要连接的socket的名字以及类型。

二, Linux中的Local socket

A UNIX domain socket address is represented in the following

structure:

#define UNIX_PATH_MAX 108

struct sockaddr_un {

sa_family_t sun_family; /* AF_UNIX */

char sun_path[UNIX_PATH_MAX]; /* pathname */

};

Linux通过sockaddr_un来指定特定的socket,下面是关于socket的说明:

* pathname: a UNIX domain socket can be bound to a null-terminated

filesystem pathname using bind(2). When the address of a pathname

socket is returned (by one of the system calls noted above), its

length is

offsetof(struct sockaddr_un, sun_path) + strlen(sun_path) + 1

and sun_path contains the null-terminated pathname. (On Linux,

the above offsetof() expression equates to the same value as

sizeof(sa_family_t), but some other implementations include other

fields before sun_path, so the offsetof() expression more portably

describes the size of the address structure.)

For further details of pathname sockets, see below.

* unnamed: A stream socket that has not been bound to a pathname

using bind(2) has no name. Likewise, the two sockets created by

socketpair(2) are unnamed. When the address of an unnamed socket

is returned, its length is sizeof(sa_family_t), and sun_path

should not be inspected.

* abstract: an abstract socket address is distinguished (from a

pathname socket) by the fact that sun_path[0] is a null byte

('\0'). The socket's address in this namespace is given by the

additional bytes in sun_path that are covered by the specified

length of the address structure. (Null bytes in the name have no

special significance.) The name has no connection with filesystem

pathnames. When the address of an abstract socket is returned,

the returned addrlen is greater than sizeof(sa_family_t) (i.e.,

greater than 2), and the name of the socket is contained in the

first (addrlen - sizeof(sa_family_t)) bytes of sun_path. The

abstract socket namespace is a nonportable Linux extension.

简单来说,"Pathname"方式在sun_path变量中指定路径名字,"abstract"方式sun_path的首位一定要是’\0',并且按照它要求的特定方式设置path,“unamed”方式不需要指定名字。

“Pathname”方式对于android中的FILESYSTEM, "abstract"对于android中的“ABSTRACT”,“unamed”非命名的应该是在最开始的时候就创建一对socket,然后利用这一对socket来通信。

对于跨平台的socket通信开发,一定要指定相同的LocalSocket方式,否则通信不会成功。对于相同的平台,可以不用指定,都是用系统默认的方式大部分时候也是没有问题的。

linux local socket,关于Local socket相关推荐

  1. 解决Linux服务器磁盘爆满导致的MySQ错误Can‘t connect to local MySQL server through socket ‘/var/lib/mysql/mysql.sock

    @[解决Linux服务器磁盘爆满导致的MySQ错误Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.so ...

  2. Linux下自动备份MySQL数据库及Can‘t connect to local MySQL server through socket和you need (at least one of) 解决e

    Linux下自动备份MySQL数据库及Can't connect to local MySQL server through socket和Access denied; you need (at le ...

  3. 【linux】Can't connect to local MySQL server through socket和Plugin 'auth_socket' is not loaded报错...

    真的是一次吐血的经历,弄了两个多小时才弄好. 问题1:直接登陆root用户报错 ERROR 2002 (HY000): Can't connect to local MySQL server thro ...

  4. #2002-The server is not responding (or the local MySQL server's socket is not correctly configur

    #2002-The server is not responding (or the local MySQL server's socket is not correctly configured) ...

  5. ERROR 2002 (HY000): Can’t connect to local MySQL server through socket ‘/var mysql 启动不了

    2019独角兽企业重金招聘Python工程师标准>>> ps -A | grep -i mysql kill 列出来的进程 service mysql start 我的问题就解决了 ...

  6. ERROR 2002 (HY000): Can‘t connect to local MySQL server through socket ‘/var/run/mysqld/mysqld.sock

    问题描述 今天阿里云服务器安装mysql的收,遇到了一个很熟悉的问题 输入 #mysql -u root -pERROR 2002 (HY000): Can't connect to local My ...

  7. ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysq

    http://hi.baidu.com/magecommerce/item/962c5a329db1eef1a9842809 配置文件设置不正确,也可能导致mysql.sock文件无法创建,消除错误日 ...

  8. MESSAGE: [unixODBC][MySQL][ODBC 3.51 Driver]Can't connect to local MySQL server through socket '/tmp

    MESSAGE: [unixODBC][MySQL][ODBC 3.51 Driver]Can't connect to local MySQL server through socket '/tmp ...

  9. 解决 ERROR 2002 (HY000) Can‘t connect to local MySQL server through socket ‘tmpmysql.sock‘

    遇到的问题是这样的~ 本机环境~WSL+WIN10 WSL2~Fedora35 MySQL~8.0.27 遇到的问题~ 每次重启机器就会遇到下面这个问题--------->>>> ...

  10. ERROR 2002 (HY00O) : Can‘t connect to local MySQL server through socket ‘ /var/ tib/ mysqL /mysgL.s

    问题 笔者在linux下安装mariadb后, 更改字符集编码(为utf8mb4),更改后退出mysql重启报错 ERROR 2002 (HY00O) : Can't connect to local ...

最新文章

  1. “”开天眼“”,天地分割效果
  2. MySQL使用INSERT插入多条记录
  3. [转+总结]Linux虚拟系统安装VMware Tools总结
  4. 中文分词_中文分词及其应用
  5. echarts 中 symbol 自定义图片
  6. Mac 配置selenium连接chrome
  7. 使用Scrapy框架编写爬虫
  8. dell 如何给raid分区_用U盘启动盘给Dell服务器装系统找不到RAID阵列解决办法
  9. sql server 配置管理器里为什么是32位_Windows Server2012 配置打印服务器图文教程
  10. java代码_【JAVA虚拟机(JVM)精髓】05-Java代码的执行过程
  11. FastFel解析一个公式的步骤
  12. 电脑远程连接已停止工作 解决方案
  13. 计算机综合应用技能,系统测评计算机综合应用技能期末作业题稿.doc
  14. ABAP 生产订单的创建与修改函数
  15. 使用TensorFlow XLA辅助实现BERT预训练加速
  16. MySQL中主键和unique的区别
  17. HL6601高性价比多种快充协议芯片QC3.0QC2.0华为FCP,SCP.VOOV苹果三星快充协议
  18. typescript学习笔记1-tsconfig.json配置和变量类型声明
  19. CSS从入门到精通——文本与字体样式1.0
  20. python适合做网站吗_零基础学python—做网站

热门文章

  1. matlab设计滤波器的工具箱,matlab工具箱设计滤波器
  2. 数字信号处理-9-离散余弦变换
  3. [TPAMI-2023] Effective Local and Global Search for Fast Long-Term Tracking
  4. 爬虫学习笔记:爬取古诗文网
  5. RV1109_RV1126 EVB开发板环境搭建及使用总结
  6. 微信红包 开发前的准备
  7. 什么是你的高光时刻?
  8. Qt Creator Windows 修改外观字体
  9. Gitlab集成阿里巴巴P3C-PMD代码质量检测插件
  10. linux下给CPU增加指定百分比的压力