首页 > 编程知识 正文

linux进程间通信socket,socket底层实现原理

时间:2023-05-06 03:19:07 阅读:113026 作者:4579

实施IPC主要有两种方法

共享内存

消息传递

概念介绍UNIX域套接字也称为进程间通信(IPC )套接字,用于实现同一主机上的进程间通信。 套接字原本是为网络通信而设计的,但在套接字框架上IPC的结构得到了发展。 是UNIX域套接字。 网络套接字也可以通过loopback地址127.0.0.1用于同一主机的进程间通信,但UNIX域套接字用于IPC更高效。 无需通过网络协议栈进行拆包、计算校验和、维护序列号和响应等,只需在进程之间复制APP应用层数据即可。 这是因为IPC机制本质上是可靠的通信,而网络协议是为不可靠的通信而设计的。

UNIX域套接字全双工,API接口含义丰富,与其他IPC机制相比具有明显优势,已成为目前应用最广泛的IPC机制。 例如,X Window服务器和GUI程序之间通过UNIX域套接字进行通信。

UNIX域套接字是POSIX标准的组件,因此请不要被名称所迷惑。 linux系统也支持这一点。

使用UNIX域套接字的步骤与网络套接字非常类似。 另外,首先调用套接字(以创建套接字文件描述符。 套接字) )函数的参数如下:

family :如果指定http://www.Sina.com /,则使用AF_UNIX在系统上创建套接字文件,不同的进程通过读写该文件来实现通信。 您可以选择type:sock_dgram或SOCK_STREAM。 SOCK_STREAM是指提供连续、可靠、双向、面向连接的比特流。 SOCK_DGRAM意味着提供固定长度、不可靠且无连接的通信协议。 参数必须指定为0。 UNIX域套接字与网络套接字编程最明显的区别是AF_UNIX的差异。 UNIX域套接字由结构地址格式表示,网络编程由sockaddr_un结构表示。 网络编程的套接字地址为sockaddr_in,UNIXdomain套接字的地址为套接字类型IP 地址加端口号,该套接字文件以bind ()

网络套接字的编程很相似,在绑定之后侦听。 这表示通过bind的地址(套接字文件)提供服务。

接下来,必须使用accept ) )函数初始化连接。 accept ) )为每个连接创建新套接字,并从监听队列中删除该连接

详情请参照以下博文。

UNIX域套接字介绍

sockaddr_un和sockaddr_in

增强UNIX域套接字进程凭据的安全性

进程凭据是UNIXdomainsocket(af_UNIX )文件在文件系统中的路径上的pid、uid和gid信息。

在服务端进行安全加固时,请访问发送方

只有AF_UNIX而不是AF_INET的原因很简单,AF_INET可能都不在同一台计算机上。 pid、uid、gid没有意义。

3359 blog.csdn.net/ayu _ ag/article/details/52413874

使用UNIX域套接字时,请使用socket server作为接收方,socket client作为发送方

要获取示例代码服务端#define _GNU_SOURCE //进程凭据,必须打开宏定义。 此宏定义必须放在编译的开头。 #include sys/socket.h //定义了cred结构。 进程凭据(pid uid和gid ) include stdio.h # include unistd.h # include string.h # include stdlib.h # includesys/un.h/h/h

dr;int listenfd = socket(AF_UNIX, SOCK_STREAM, 0);if (listenfd < 0) {printf("create socket failedn");return -1;}memset(&server_addr, 0, sizeof(server_addr));strcpy(server_addr.sun_path, server_socket_path); // 初始化socket文件路径unlink(server_socket_path); // 一定要删除掉旧文件重新创建,否则会报错server_addr.sun_family=AF_UNIX; // 初始化socket family为AF_UNIX,使用本地IPC模式if (bind(listenfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {close(listenfd);return -1;}if (listen(listenfd, 128) < 0) { // 最大支持连接128个clientclose(listenfd);return -1;}int connfd;struct sockaddr_un client_addr;int msglen;while (1) { // 循环监听,等待client连接printf("[*] waiting for client connectingn");if ((connfd = accept(listenfd, (struct sockaddr *)&client_addr, &msglen)) < 0) {continue;}struct ucred cred; // 保存client的pid uid和gidsocklen_t len = sizeof(struct ucred);getsockopt(connfd, SOL_SOCKET, SO_PEERCRED, &cred, &len);printf("[*] Credentials from SO_PEERCRED: pid=%d, uid=%d, gid=%dn", cred.pid , cred.uid, cred.gid);printf("[*] close connectn");close(connfd);}close(listenfd);return 0;} 客户端 #define _GNU_SOURCE // 如果要获取进程凭据,则需要打开该宏定义才可以,这个宏定义一定要放在编译最开始#include <sys/socket.h> // 定义了cred结构体,用于存放进程凭据(pid uid和gid)#include <stdio.h>#include <unistd.h>#include <string.h>#include <sys/un.h> // 定义了sockaddr_un结构体char *server_socket_path="server.socket"; // 这里跟server保持一致int main(){struct sockaddr_un server_addr;int clientfd = socket(AF_UNIX, SOCK_STREAM, 0);if (clientfd < 0) {printf("create socket faield!n");return -1;}memset(&server_addr, 0, sizeof(server_addr));server_addr.sun_family=AF_UNIX;strcpy(server_addr.sun_path, server_socket_path);if (connect(clientfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {printf("connect to server failed!n");close(clientfd);return -1;}close(clientfd);return 0;}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。