【无标题】
进程间通讯:域套接字(Unix Domain Sockets)
一、简介
域套接字是一种在同一台机器上进行进程间通讯的机制(Inter-Process Communication, IPC),也称为本地套接字或文件系统套接字。与网络套接字不同,Unix套接字不需要经过网络协议栈,因此性能上更为高效。域套接字支持流(类似TCP)和数据报(类似UDP)两种模式;
域套接字不经过网络协议栈是指数据传输不去要经过IP层的路由、不需要TCP/UDP等传输层协议的封包域解包处理,不需要网络接口层的参与,网络套接字则需要完成的网络协议栈处理;
二、原理图
普通网络套接字数据传输过程:
域套接字数据传输过程:
三、主要特点
- 本地通信:Unix 域套接字仅限于同一主机上的进程之间通信。
- 高性能:由于不经过网络协议栈,通信速度更快。
- 安全性:文件系统的权限管理可以用来控制访问。
- 灵活的数据传输:支持字节流(SOCK_STREAM)和数据报(SOCK_DGRAM)两种模式。
- 文件系统路径:每个 Unix 域套接字都有一个文件系统路径,可以在文件系统中查看和操作。
四、基本概念
- 套接字地址结构:
struct sockaddr_un
用于表示 Unix 域套接字的地址。 - 套接字类型:
- SOCK_STREAM:提供面向连接的、可靠的数据传输服务,类似于 TCP。
- SOCK_DGRAM:提供无连接的、不可靠的数据报服务,类似于 UDP。
五、代码示例
1、客户端代码示例
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
// 信号处理器函数
void sigpipe_handler(int signum) {
if (signum == SIGPIPE) {
fprintf(stderr, "Caught SIGPIPE, connection closed by server\n");
// 你可以选择在这里关闭套接字并退出程序,或者继续处理其他逻辑
}
}
int main() {
// 设置 SIGPIPE 信号处理器
signal(SIGPIPE, sigpipe_handler);
int client_fd;
struct sockaddr_un client_addr;
// 创建 UNIX 域套接字
client_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (client_fd == -1) {
perror("socket failed");
return 1;
}
// 初始化客户端地址
client_addr.sun_family = AF_UNIX;
strcpy(client_addr.sun_path, "/tmp/unix_socket");
// 连接到服务器
int ret = connect(client_fd, (struct sockaddr *)&client_addr, sizeof(client_addr));
if (ret != 0) {
fprintf(stderr, "Reconnect failed, exiting...\n");
close(client_fd);
return -1;
}
while (true)
{
char buffer[1024];
printf("please write message: ");
if (fgets(buffer, sizeof(buffer), stdin) != NULL)
{
// 去除可能的换行符
size_t len = strlen(buffer);
if (len > 0 && buffer[len - 1] == '\n') {
buffer[len - 1] = '\0';
}
// 发送数据到服务器
int bytes_sent = write(client_fd, buffer, strlen(buffer));
if (bytes_sent == -1) {
if (errno == EPIPE) {
fprintf(stderr, "Write error: Broken pipe, connection closed by server\n");
break;
} else {
perror("write failed");
break;
}
}
printf("send message: %s\n", buffer);
// 接收回显消息
memset(buffer, 0, 1024);
int bytes_received = read(client_fd, buffer, 1024 - 1);
if (bytes_received > 0) {
printf("Received from server: %s\n", buffer);
} else {
perror("read failed");
}
}
else
{
// 如果fgets返回NULL,可能是因为输入错误或者EOF,这里选择退出循环
printf("write message error\n");
break;
}
}
close(client_fd);
return 0;
}
2、服务端示例代码:
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int server_fd, client_socket;
struct sockaddr_un server_addr, client_addr;
// 创建套接字
server_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (server_fd == -1) {
perror("socket failed");
exit(EXIT_FAILURE);
return 1;
}
// 设置服务器地址
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sun_family = AF_UNIX;
strcpy(server_addr.sun_path, "/tmp/unix_socket");
unlink(server_addr.sun_path);
// 绑定套接字
if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("bind failed");
exit(EXIT_FAILURE);
return 1;
}
// 监听连接
if (listen(server_fd, 5) == -1) {
perror("listen failed");
close(server_fd);
return 1;
}
printf("Waiting for connection...\n");
// 接受连接
client_socket = accept(server_fd, NULL, NULL);
if (client_socket == -1) {
perror("accept failed");
close(server_fd);
return 1;
}
while (true)
{
char buffer[1024];
printf("Waiting for read data...\n");
int bytes_received = read(client_socket, buffer, sizeof(buffer)-1);
if (bytes_received > 0) {
buffer[bytes_received] = '\0';
for (size_t i = 0; i < bytes_received; i++)
{
printf("Received data client: %c\n", buffer[i]);
}
printf("Received message from client: %s -----%d \n", buffer, bytes_received);
// 发送回显消息
// write(client_socket, buffer, bytes_received);
if (write(client_socket, buffer, bytes_received) == -1) {
perror("write failed");
close(client_socket);
break;
}
} else if (bytes_received == 0) {
printf("Client disconnected.\n");
break;
} else {
perror("read failed");
break;
}
}
close(server_fd);
unlink(client_addr.sun_path);
return 0;
}
参考文献:https://mp.weixin.qq.com/s/R6yu5IKothuHF0IRCDq_vQ
原文地址:https://blog.csdn.net/xiaofeilongyu/article/details/143716979
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!