Ahao's Technical Blog Ahao's Technical Blog
首页
  • 001.基础篇
  • 002.玩转AOSP篇
  • 003.学穿Binder篇
  • 004.基础组件篇
  • 005.系统启动过程分析
  • 006.Hal开发入门与实践
  • 007.显示系统
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

阿豪讲Framework

不积跬步无以至千里
首页
  • 001.基础篇
  • 002.玩转AOSP篇
  • 003.学穿Binder篇
  • 004.基础组件篇
  • 005.系统启动过程分析
  • 006.Hal开发入门与实践
  • 007.显示系统
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 基础篇

  • 玩转AOSP篇

  • 学穿Binder篇

  • 基础组件篇

    • 001.Android 平台智能指针使用与分析
    • 002.弱引用 wp 的作用
    • 003.Linux eventfd 原理与实践
    • 004.Linux IO 多路复用 epoll 机制
    • 005.Linux timerfd 的基本使用
    • 006.Android Native Looper 机制
    • 007.Android Java Looper 机制
    • 008.Handler 同步屏障机制
    • 009.IdleHanlder 原理与使用
    • 010.Android 属性系统入门
    • 011.属性文件生成过程分析
    • 012.如何添加系统属性
    • 013.属性与 Selinux
    • 014.属性系统源码分析一
    • 015.属性系统源码分析二
    • 016.属性系统源码分析三
    • 017.Unix Domain Socket 使用解析之 UDP 篇
    • 018.Unix Domain Socket 使用解析之 TCP 篇
    • 019.Android 中的 Unix Domain Socket 使用解析
    • 020.socketpair 使用解析
    • 021.Android 平台日志系统整体框架
    • 022.logd 守护进程初始化过程
    • 023.客户端写日志过程分析
    • 024.logd 写日志过程分析一
    • 025.logd 写日志过程分析二
    • 026.logd 读日志过程分析
    • 027.Android 平台日志丢失问题分析
  • 系统启动过程分析

  • Hal开发入门与实践

  • 显示系统

  • Framework
  • 基础组件篇
阿豪
2023-11-15

020.socketpair 使用解析

socketpair 在 Framework 的 Native 层中有大量的使用,接下来我们对 socketpair 做基本的了解。

socket 基于 c/s 模型,需要客户端与服务端进行连接,连接还需要知道服务端的 ip,如果是 unix domain socket ,则需要对应的文件路径。两端连接后可以实现服务端和客户端的双向通信,这种情况一般比较适合于很多个客户端对应一个服务的情况。但是如果说本身就只是单独 2 个进程进行相互通信的需求,我们就可以使用 socketpair api,对于 socketpair ,不需要 connect,也不需要 ip 或者路径,它是匿名的,在 socketpair 初始化时就已经确定了 2 个对应的 socket 的 fd,直接读写这两个 fd 即可完成通信。

接下来我们来看具体的 API:

#include <sys/types.h>
#include <sys/socket.h>
int socketpair(int d, int type, int protocol, int sv[2]);
1
2
3
  • socketpair() 函数用于创建一对无名的、相互连接的套接字
  • 如果函数成功,则返回 0,创建好的套接字分别是 sv[0] 和 sv[1];否则返回 -1,错误码保存于 errno 中。

我们可以直接读写这两个套接字来进行通信,在使用过程中有以下几个注意点:

  1. 这对套接字可以用于全双工通信,每一个套接字既可以读也可以写。例如,可以往sv[0]中写,从sv[1]中读;或者从sv[1]中写,从sv[0]中读;
  2. 如果往一个套接字(如sv[0])中写入后,再从该套接字读时会阻塞,只能在另一个套接字中(sv[1])上读成功;
  3. 读、写操作可以位于同一个进程,也可以分别位于不同的进程,如父子进程。如果是父子进程时,一般会功能分离,一个进程用来读,一个用来写。因为文件描述副sv[0]和sv[1]是进程共享的,所以读的进程要关闭写描述符, 反之,写的进程关闭读描述符。

接下来看两个简单的 demo:

// 同进程
#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <error.h> 
#include <errno.h> 
#include <sys/socket.h> 
#include <stdlib.h> 
 
const char* str = "SOCKET PAIR TEST.";
 
int main(int argc, char* argv[]){
    char buf[128] = {0};
    int socket_pair[2]; 
    pid_t pid; 
 
    if(socketpair(AF_UNIX, SOCK_STREAM, 0, socket_pair) == -1 ) { 
        printf("Error, socketpair create failed, errno(%d): %s\n", errno, strerror(errno));
        return EXIT_FAILURE; 
    } 
 
    int size = write(socket_pair[0], str, strlen(str));
    //可以读取成功;
    read(socket_pair[1], buf, size);
    printf("Read result: %s\n",buf);
    return EXIT_SUCCESS;    
} 

//不同进程
#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <error.h> 
#include <errno.h> 
#include <sys/socket.h> 
#include <stdlib.h> 
 
const char* str = "SOCKET PAIR TEST.";
 
int main(int argc, char* argv[]){
    char buf[128] = {0};
    int socket_pair[2]; 
    pid_t pid; 
 
    if(socketpair(AF_UNIX, SOCK_STREAM, 0, socket_pair) == -1 ) { 
        printf("Error, socketpair create failed, errno(%d): %s\n", errno, strerror(errno));
        return EXIT_FAILURE; 
    } 
 
    pid = fork();
    if(pid < 0) {
        printf("Error, fork failed, errno(%d): %s\n", errno, strerror(errno));
        return EXIT_FAILURE;
    } else if(pid > 0) {
        //关闭另外一个套接字
        close(socket_pair[1]);
        int size = write(socket_pair[0], str, strlen(str));
        printf("Write success, pid: %d\n", getpid());
 
    } else if(pid == 0) {
        //关闭另外一个套接字
        close(socket_pair[0]);
        read(socket_pair[1], buf, sizeof(buf));        
        printf("Read result: %s, pid: %d\n",buf, getpid());
    }
 
    for(;;) {
        sleep(1);
    }
 
    return EXIT_SUCCESS;    
} 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
019.Android 中的 Unix Domain Socket 使用解析
021.Android 平台日志系统整体框架

← 019.Android 中的 Unix Domain Socket 使用解析 021.Android 平台日志系统整体框架→

最近更新
01
如何调试 SurfaceFlinger
10-05
02
SurfaceFlinger 概述
10-05
03
HWC 接口分析
10-05
更多文章>
Theme by Vdoing | Copyright © 2020-2025 AHao Framework | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式