IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> Android SocketListener、FrameworkListener 分析 -> 正文阅读

[网络协议]Android SocketListener、FrameworkListener 分析

1. xxx.rc 中使用 /dev/socket/xxx

logd.rc 中 有 "socket logd stream 0666 logd logd" 以及 "socket logdr seqpacket 0666 logd logd"

这样的写法,实际会将logd 服务 与??"/dev/socket/logd" "dev/socket/logdr" socket节点进行绑定

?/system/core/logd/logd.rc
service logd /system/bin/logd
    socket logd stream 0666 logd logd
    socket logdr seqpacket 0666 logd logd
    socket logdw dgram+passcred 0222 logd logd
    file /proc/kmsg r
    file /dev/kmsg w
    user logd
    group logd system package_info readproc
    capabilities SYSLOG AUDIT_CONTROL
    priority 10
    task_profiles ServiceCapacityLow

2. SocketListener 分析

1)?通过继承?SocketListener 类,

SocketListener, class LogReader : public SocketListener {}"

2) 实现构造方法:

LogListener::LogListener(LogBuffer* buf, LogReader* reader)
? ? : SocketListener(getLogSocket(), false), logbuf(buf), reader(reader) {}

3) 通过?startListener()? 以及重载的 onDataAvailable()方法 完成通信

system/core/libsysutils/include/sysutils/SocketListener.h
class SocketListener {
    bool                    mListen;
    const char              *mSocketName;
    int                     mSock;
    std::unordered_map<int, SocketClient*> mClients;
    pthread_mutex_t         mClientsLock;
    int                     mCtrlPipe[2];
    pthread_t               mThread;
    bool                    mUseCmdNum;

public:
    SocketListener(const char *socketName, bool listen);
    SocketListener(const char *socketName, bool listen, bool useCmdNum);
    SocketListener(int socketFd, bool listen);

    virtual ~SocketListener();
    int startListener();
    int startListener(int backlog);
    int stopListener();

    void sendBroadcast(int code, const char *msg, bool addErrno);

    void runOnEachSocket(SocketClientCommand *command);

    bool release(SocketClient *c) { return release(c, true); }

protected:
    virtual bool onDataAvailable(SocketClient *c) = 0;

private:
    static void *threadStart(void *obj);

    // Add all clients to a separate list, so we don't have to hold the lock
    // while processing it.
    std::vector<SocketClient*> snapshotClients();

    bool release(SocketClient *c, bool wakeup);
    void runListener();
    void init(const char *socketName, int socketFd, bool listen, bool useCmdNum);
};

natvie 代码里面通过 android_get_control_socket(xxx) 获取 "/dev/socket/xxx"

/system/core/libsysutils/src/SocketListener.cpp

SocketListener::SocketListener(const char *socketName, bool listen) {
    init(socketName, -1, listen, false)
}
SocketListener::SocketListener(int socketFd, bool listen) {
  init(nullptr, socketFd, listen, false)
}

void SocketListener::init(const char *socketName, int socketFd, bool listen, bool 
  useCmdNum) {
  mListen = listen
  mSocketName = socketName
  mSock = socketFd
  mUseCmdNum = useCmdNum
  pthread_mutex_init(&mClientsLock, nullptr)
}

int SocketListener::startListener() {
  return startListener(4)
}

int SocketListener::startListener(int backlog) {
  if (mSocketName) {
    // 重要,获取 socket 的地方,通过 mSocketName 获取socket
    mSock = android_get_control_socket(mSocketName))
    fcntl(mSock, F_SETFD, FD_CLOEXEC)
  }

  if (mListen && listen(mSock, backlog) < 0)
  else if(!mListen)
    mClients[mSock] = new SocketClient(mSock, false, mUseCmdNum)
    
  (pthread_create(&mThread, nullptr, SocketListener::threadStart, this)
}
  
void *SocketListener::threadStart(void *obj) {
  SocketListener *me = reinterpret_cast<SocketListener *>(obj)
  me->runListener()
}

// 继承于 SocketListener 的子类,通过重载 onDataAvailable()方法,基于这个模型实现通信的
void SocketListener::runListener() {
  while (true) {
    for (SocketClient* c : pending) {
      onDataAvailable(c)
    }
  }
}

3.?FrameworkListener 分析

FrameworkListener 继承于 SocketListener ,也可以基于 FrameworkListener 进行通信设计

通过 registerCmd 方法注册,然后调用对应 FrameworkCommand 的runCommand()方法

system/core/libsysutils/include/sysutils/FrameworkListener.h
class FrameworkListener : public SocketListener {}

/system/core/libsysutils/src/FrameworkListener.cpp

FrameworkListener::FrameworkListener(const char *socketName, bool withSeq) :
  SocketListener(socketName, true, withSeq) {
  init(socketName, withSeq)
}

FrameworkListener::FrameworkListener(const char *socketName) :
  SocketListener(socketName, true, false) {
  init(socketName, false)
}

void FrameworkListener::init(const char* /*socketName*/, bool withSeq) {
  mWithSeq = withSeq
  mSkipToNextNullByte = false
}

bool FrameworkListener::onDataAvailable(SocketClient *c) {
  len = TEMP_FAILURE_RETRY(read(c->getSocket(), buffer, sizeof(buffer)))
  for (i = 0; i < len; i++) {
    if (buffer[i] == '\0') {
       dispatchCommand(c, buffer + offset)
       offset = i + 1
    }
  }
}

void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) {
  while(*p) {
    for (auto* c : mCommands) {
      if (!strcmp(argv[0], c->getCommand())) {
        if (c->runCommand(cli, argc, argv))
      }
    }
  }
}

// 通过 registerCmd 方法注册,然后调用对应 FrameworkCommand 的runCommand()方法
void FrameworkListener::registerCmd(FrameworkCommand *cmd) {
  mCommands.push_back(cmd)
}

4. 通过 SocketListener 及 FrameworkListener 实现通信例子

// 继承 SocketListener 实现通信
/system/core/logd/LogListener.cpp
  LogListener::LogListener(LogBuffer* buf, LogReader* reader)
    : SocketListener(getLogSocket(), false), logbuf(buf), reader(reader) {}
  
  int LogListener::getLogSocket() {
    static const char socketName[] = "logdw";
    int sock = android_get_control_socket(socketName);
    if (sock < 0) {
      sock = socket_local_server(
        socketName, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_DGRAM);
      setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))
    }
    return sock
  }

  bool LogListener::onDataAvailable(SocketClient* cli) {
  }

/system/core/logd/CommandListener.cpp
  int CommandListener::ClearCmd::runCommand(SocketClient* cli, int argc,char** argv) {
    if (argc < 2) {
      cli->sendMsg("Missing Argument");
      return 0;
    }
    cli->sendMsg(mBuf.clear((log_id_t)id, uid) ? "busy" : "success")
    return 0
  }

// 服务端,守护进程 logd

/system/core/logd/main.cpp
  int main(int argc, char* argv[]) {
    // 继承于 SocketListener, class LogReader : public SocketListener {}
    LogReader* reader = new LogReader(logBuf)
    reader->startListener()
    
    // 继承于 SocketListener, class LogListener : public SocketListener {}
    LogListener* swl = new LogListener(logBuf, reader)
    swl->startListener(600)
    
    // 继承于FrameworkListener, class CommandListener : public FrameworkListener {}
    CommandListener* cl = new CommandListener(logBuf, reader, swl)
    cl->startListener() 
  }

// 使用者客户端, logcat?


/system/core/logcat/logcat.cpp
int main(int argc, char** argv) {
  return logcat.Run(argc, argv)
}
int Logcat::Run(int argc, char** argv) {
  while (!max_count_ || print_count_ < max_count_) {
    int ret = android_logger_list_read(logger_list.get(), &log_msg)
  }
}

/system/core/liblog/logd_reader.cpp
int LogdRead(struct logger_list* logger_list, struct log_msg* log_msg) {
  int ret = logdOpen(logger_list)
}

static int logdOpen(struct logger_list* logger_list) {
  sock = socket_local_client("logdr", SOCK_SEQPACKET)
  ret = TEMP_FAILURE_RETRY(write(sock, buffer, cp - buffer))
}

static int socket_local_client(const std::string& name, int type) {
  std::string path = "/dev/socket/" + name;
  strlcpy(addr.sun_path, path.c_str(), sizeof(addr.sun_path))
  int fd = socket(AF_LOCAL, type | SOCK_CLOEXEC, 0)
  connect(fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr))
}

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-11-27 10:15:37  更:2021-11-27 10:16:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年7日历 -2024/7/6 8:13:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码