好用的进程间通信方式---UnixDomainSocket
发布时间:2022-12-12 11:03:59 所属栏目:Unix 来源:
导读: 什么是unixsocket
socket大家应该很熟悉,以tcp/ip协议族为传输协议,用于跨主机通信,而unixsocket就是在socket的框架上发展出一种IPC机制(进程间通信),UDS(UNIX Domain Socket)提供面向流和面向数
socket大家应该很熟悉,以tcp/ip协议族为传输协议,用于跨主机通信,而unixsocket就是在socket的框架上发展出一种IPC机制(进程间通信),UDS(UNIX Domain Socket)提供面向流和面向数
|
什么是unixsocket socket大家应该很熟悉,以tcp/ip协议族为传输协议,用于跨主机通信,而unixsocket就是在socket的框架上发展出一种IPC机制(进程间通信),UDS(UNIX Domain Socket)提供面向流和面向数据包两种API接口,类似于TCP和UDP,其中SOCK_STREAM是很可靠的,消息既不会丢失也不会顺序错乱,比传统的socket效率更高,一般是tcp传输的两倍unix进程通信,并且不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是将应用层数据从一个进程拷贝到另一个进程。 unixsocket服务端和客户端连接及发送消息的过程如下: unixsocket在k8s sidecar中的实践 unixsocket用途也很广泛,比如docker与宿主机的数据传输和信息交换: 其次,还有一个好处是,这两个进程完全可以用不同的语言写,然后都用unixsocket去通信。 好啦,说了这么多让我介绍一种k8s的pod业务场景,比如说我们主业务是一个数据分析或规则引擎,它是需要有一些配置可供用户在前端配置的,比如说规则的开关啊,数据分析文件大小啊等等,然后分析出来的结果也需要发送出去,向用户展示,或者是有一些指标需要定期进行健康检查,比如说cpu使用率啊,内存占用率啊等等,因为性能的要求,一般数据分析或规则匹配引擎都是C/C++写的,而C非常不擅长去与restful接口去通信,以及配置的json序列反序列化的字符串处理,因此,我可以用考虑在同一个pod中起一个sidecar,而这个sidecar服务可以用Go写,然后主服务和sidecar可以用unixsocket进行通信,前提只要这两者有一个共享挂载的目录,比如说是:"/root/unixsocket/sidecar.sock",整体思路如下所示: //C服务端,无所谓了,两边都需要传一些信息 #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #define UNIX_DOMAIN "/root/unixsocket/sidecar.sock" #define READ_FROM_CLIENT 0X01 #define WRITE_TO_CLIENT 0x02 int main(void) { socklen_t clt_addr_len; int listen_fd; int com_fd; int ret; //int i; static char data_buf[1024]; int len; struct sockaddr_un clt_addr; struct sockaddr_un srv_addr; listen_fd = socket(PF_UNIX, SOCK_STREAM, 0); if(listen_fd < 0) { perror("cannot create communication socket"); return 1; } //set server addr_param srv_addr.sun_family = AF_UNIX; strcpy(srv_addr.sun_path,UNIX_DOMAIN); unlink(UNIX_DOMAIN); //bind sockfd & addr ret = bind(listen_fd, (struct sockaddr*)&srv_addr, sizeof(srv_addr)); if(ret == -1) { perror("cannot bind server socket"); close(listen_fd); unlink(UNIX_DOMAIN); return 1; } //listen sockfd ret = listen(listen_fd,1); if(ret == -1) { perror("cannot listen the client connect request"); close(listen_fd); unlink(UNIX_DOMAIN); return 1; } while(1) { //have connect request use accept len = sizeof(clt_addr); com_fd = accept(listen_fd,(struct sockaddr*)&clt_addr,&len); if(com_fd < 0) { perror("cannot accept client connect request"); close(listen_fd); unlink(UNIX_DOMAIN); return 1; } //read and printf sent client info printf("\nReceive from client:\n"); memset(data_buf, 0, 1024); read(com_fd, data_buf, sizeof(data_buf)); printf("Request is %s\n", data_buf); memset(data_buf, 0, 1024); strcpy(data_buf, "send message to client!!"); write(com_fd, data_buf, sizeof(data_buf)); printf("send message to client\n:"); memset(data_buf, 0, 1024); close(com_fd); } close(listen_fd); unlink(UNIX_DOMAIN); return 0; } //Go客户端 package main import ( "bufio" "fmt" "net" "time" ) var quitSemaphore chan bool func main() { var unixAddr *net.UnixAddr unixAddr, _ = net.ResolveUnixAddr("unix", "/root/unixsocket/sidecar.sock") conn, _ := net.DialUnix("unix", nil, unixAddr) defer conn.Close() fmt.Println("connected!") go onMessageRecived(conn) b := []byte("time\n") conn.Write(b) <-quitSemaphore } func onMessageRecived(conn *net.UnixConn) { reader := bufio.NewReader(conn) for { msg, err := reader.ReadString('\n') fmt.Println(msg) if err != nil { quitSemaphore <- true break } time.Sleep(time.Second) b := []byte(msg) conn.Write(b) } } (编辑:PHP编程网 - 钦州站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
推荐文章
站长推荐

浙公网安备 33038102330484号