当前位置: 首页 > article >正文

Unix 域协议汇总整理

Unix 域协议是一种用于同一台计算机上进程间通信(IPC)的技术。它提供了一种比基于网络的套接字更高效的方式来在本地进程中交换数据。Unix 域协议使用文件系统作为通信的媒介,并且只限于在同一台计算机上运行的进程之间进行通信。

da7e770630a54b20a731a0575338adfa.jpeg

Unix 域套接字类型

Unix 域套接字支持两种主要类型:

  1. 流套接字 (SOCK_STREAM):类似于 TCP 套接字,提供面向连接的服务,保证数据按顺序传输,并且不会丢失或重复。
  2. 数据报套接字 (SOCK_DGRAM):类似于 UDP 套接字,不保证数据按顺序传输,也不提供错误恢复机制。

Unix 域套接字的优点

  • 高效:由于数据不需要离开本机,所以 Unix 域套接字比网络套接字更快。
  • 安全:通信仅限于本地,减少了网络攻击的风险。
  • 简单:使用与网络套接字相同的 API。

Unix 域套接字的缺点

  • 局限性:只能在同一台计算机上使用。
  • 可移植性:仅限于 Unix 和类 Unix 系统,不适用于 Windows 等其他操作系统。

Unix 域套接字的使用

Unix 域套接字的使用与网络套接字相似,但有一些关键的不同之处:

创建 Unix 域套接字

1#include <sys/un.h>
2#include <sys/socket.h>
3
4// 创建 Unix 域套接字
5int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
6if (sockfd == -1) {
7    perror("socket");
8    exit(EXIT_FAILURE);
9}

地址结构

Unix 域套接字使用 struct sockaddr_un 来表示地址:

1struct sockaddr_un addr;
2memset(&addr, 0, sizeof(addr));
3addr.sun_family = AF_UNIX;
4strncpy(addr.sun_path, "/path/to/socket", sizeof(addr.sun_path) - 1);

绑定套接字

1// 绑定套接字
2if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
3    perror("bind");
4    exit(EXIT_FAILURE);
5}

监听连接

1// 监听连接
2if (listen(sockfd, 5) == -1) {
3    perror("listen");
4    exit(EXIT_FAILURE);
5}

接受连接

1// 接受连接
2int client_sock = accept(sockfd, NULL, NULL);
3if (client_sock == -1) {
4    perror("accept");
5    exit(EXIT_FAILURE);
6}

发送和接收数据

1// 发送数据
2const char *message = "Hello, World!";
3if (send(client_sock, message, strlen(message), 0) == -1) {
4    perror("send");
5    exit(EXIT_FAILURE);
6}
7
8// 接收数据
9char buffer[1024];
10ssize_t bytes_received = recv(client_sock, buffer, 1024, 0);
11if (bytes_received == -1) {
12    perror("recv");
13    exit(EXIT_FAILURE);
14}
15buffer[bytes_received] = '\0';
16printf("Received: %s\n", buffer);

关闭套接字

1// 关闭套接字
2close(sockfd);

示例代码

下面是一个简单的 Unix 域套接字服务器端和客户端示例,演示了如何使用 Unix 域套接字进行进程间通信。

服务器端 (server.c)

1#include <sys/un.h>
2#include <sys/socket.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <unistd.h>
6#include <string.h>
7
8#define SOCKET_PATH "/tmp/unix_socket"
9
10int main() {
11    int sockfd, new_sock;
12    struct sockaddr_un addr, cli_addr;
13    char buffer[1024];
14    socklen_t len;
15
16    // 创建 Unix 域套接字
17    sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
18    if (sockfd == -1) {
19        perror("socket");
20        exit(EXIT_FAILURE);
21    }
22
23    // 清空地址结构
24    memset(&addr, 0, sizeof(addr));
25    addr.sun_family = AF_UNIX;
26    strncpy(addr.sun_path, SOCKET_PATH, sizeof(addr.sun_path) - 1);
27
28    // 绑定套接字
29    if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
30        perror("bind");
31        exit(EXIT_FAILURE);
32    }
33
34    // 监听连接
35    if (listen(sockfd, 5) == -1) {
36        perror("listen");
37        exit(EXIT_FAILURE);
38    }
39
40    // 接受连接
41    len = sizeof(cli_addr);
42    new_sock = accept(sockfd, (struct sockaddr *)&cli_addr, &len);
43    if (new_sock == -1) {
44        perror("accept");
45        exit(EXIT_FAILURE);
46    }
47
48    // 读取数据
49    ssize_t bytes_received = recv(new_sock, buffer, 1024, 0);
50    if (bytes_received == -1) {
51        perror("recv");
52        exit(EXIT_FAILURE);
53    }
54    buffer[bytes_received] = '\0';
55    printf("Received: %s\n", buffer);
56
57    // 发送响应
58    const char *response = "Hello, Client!";
59    if (send(new_sock, response, strlen(response), 0) == -1) {
60        perror("send");
61        exit(EXIT_FAILURE);
62    }
63
64    // 关闭套接字
65    close(new_sock);
66    close(sockfd);
67
68    return 0;
69}

客户端 (client.c)

1#include <sys/un.h>
2#include <sys/socket.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <unistd.h>
6#include <string.h>
7
8#define SOCKET_PATH "/tmp/unix_socket"
9
10int main() {
11    int sockfd;
12    struct sockaddr_un addr;
13    char buffer[1024];
14
15    // 创建 Unix 域套接字
16    sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
17    if (sockfd == -1) {
18        perror("socket");
19        exit(EXIT_FAILURE);
20    }
21
22    // 清空地址结构
23    memset(&addr, 0, sizeof(addr));
24    addr.sun_family = AF_UNIX;
25    strncpy(addr.sun_path, SOCKET_PATH, sizeof(addr.sun_path) - 1);
26
27    // 连接到服务器
28    if (connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
29        perror("connect");
30        exit(EXIT_FAILURE);
31    }
32
33    // 发送数据
34    const char *message = "Hello, Server!";
35    if (send(sockfd, message, strlen(message), 0) == -1) {
36        perror("send");
37        exit(EXIT_FAILURE);
38    }
39
40    // 读取响应
41    ssize_t bytes_received = recv(sockfd, buffer, 1024, 0);
42    if (bytes_received == -1) {
43        perror("recv");
44        exit(EXIT_FAILURE);
45    }
46    buffer[bytes_received] = '\0';
47    printf("Received: %s\n", buffer);
48
49    // 关闭套接字
50    close(sockfd);
51
52    return 0;
53}

编译和运行

为了编译上述代码,你可以使用以下命令:

1gcc -o server server.c
2gcc -o client client.c

然后先运行服务器:

1./server

接着运行客户端:

1./client

您应该能够在服务器和客户端之间看到数据的交换。

注意事项

  • 在创建 Unix 域套接字之前,请确保不存在旧的套接字文件。如果存在,可以手动删除或在程序开始时删除。
  • 请确保 Unix 域套接字文件具有适当的文件权限,以防止未经授权的访问。
  • 在实际应用中,可能需要处理更复杂的错误情况,比如处理连接失败的情况。
  • 使用 Unix 域套接字时,需要确保文件描述符集合在调用期间不会被其他线程或信号处理程序修改。

Unix 域套接字是一种非常高效和安全的进程间通信方式,非常适合在同一台计算机上运行的进程之间的通信。

 


http://www.kler.cn/a/470016.html

相关文章:

  • c#版本、.net版本、visual studio版本之间的对应关系
  • 第30天:Web开发-PHP应用组件框架前端模版渲染三方插件富文本编辑器CVE审计
  • Telephony Netd
  • 【信息系统项目管理师】高分论文:论信息系统项目的风险管理(资金管控系统)
  • C++虚函数(八股总结)
  • 《学校一卡通管理系统》数据库MySQL的设计与实现
  • 我用Ai学Android Jetpack Compose之Text
  • Vmware安装centos
  • 在 Ubuntu 22.04 上部署 AppArmor 应用安全教程
  • 芋道源码(无遮羞布版)Spring Boot 全景指南
  • Federation机制的实现
  • b612相机 13.5.5解锁会员hook
  • 【A I应用】1.原理入门以及应用方式
  • 『SQLite』SELECT语句查询数据
  • 机器学习基础-线性回归和逻辑回归
  • OpenGl(四) 提升Shader性能--VBO、EBO、VAO之EBO
  • Reactor测试框架之StepVerifier
  • JavaScript语言的编程范式
  • Python爬虫入门指南:从零开始抓取数据
  • Mysql--基础篇--概述
  • 专业无人机飞手培训,考证、组装、调参、维修全面技术详解
  • 网络协议安全
  • NLP论文速读|基于主动检索的渐进多模态推理
  • 【C++】AVL树|插入|单旋|双旋
  • 反向代理模块开发,
  • type1-88