深入理解Golang Unix域socket通信

news/2025/1/15 6:06:58/

Golang Socket是一种通信方式,可以在程序中通过网络发送和接收数据。主要有两种类型socket:Unix域socket(AF_UNIX)和网络socket(AF_INET|AF_INET6)。本文主要介绍这几种类型socket及其之间的区别和应用场景。

Unix域socket

Unix域socket也称为本地socket,用于在同一机器的进程间通信。实用基于文件的接口,通过文件系统路径访问,就像正常的文件。通常情况下Unix域socket比网络socket要更快、更高效,他们通常用于内部进程(IPC)或服务间通信,使用文件系统作为通信通道进行传输数据。

文件系统提供可靠的、有效的机制在进程间传输数据,仅涉及到内核。进程间通信通过读写相同的socket文件,这由内核进行管理。内核负责处理通信细节,如同步、缓存和错误处理以及确保数据按正确的顺序可靠传输。

而网络socket的通信需要涉及内核,网络栈、网络硬件,过程使用网络协议,如TCP/UDP,网络socket通过网络建立连接并传输数据。内核和网络栈处理通信细节,如路由、寻址以及纠错,网络硬件处理数据在网络中物理传输。

Golang 中 Unix与socket被创建使用net.Dial客户端或net.Linsten服务端函数,需要使用unix网络类型。举例,下面代码创建Unix域socket并监听请求连接:

// Create a Unix domain socket and listen for incoming connections.
socket, err := net.Listen("unix", "/tmp/mysocket.sock")
if err != nil {panic(err)
}

网络socket

网络socket在不同机器的进程间通信,使用tcp或udp协议。网络socket比unix域socket应用更广,可以在任何连接网络中机器进行中通信,通常为服务端-客户端方式,如web服务器和客户端应用。

Golang网络socket使用net.Dialnet.Listen函数创建,使用tcp或udp协议。举例,下面代码创建tcp socket并监听请求连接:

// Create a TCP socket and listen for incoming connections.
socket, err := net.Listen("tcp", ":8000")
if err != nil {panic(err)
}

Unix域socket示例

下面看一个示例如何使用unix域socket,下面代码使用unix域创建简单echo功能服务:

package main
import (...)func main() {sPath := "/tmp/echo.sock"// Create a Unix domain socket and listen for incoming connections.socket, err := net.Listen("unix", sPath)if err != nil {log.Fatal(err)}// Cleanup the sockfile.c := make(chan os.Signal, 1)signal.Notify(c, os.Interrupt, syscall.SIGTERM)go func() {<-cos.Remove(sPath)os.Exit(1)}()for {// Accept an incoming connection.conn, err := socket.Accept()if err != nil {log.Fatal(err)}// Handle the connection in a separate goroutine.go func(conn net.Conn) {defer conn.Close()// Create a buffer for incoming data.buf := make([]byte, 4096)// Read data from the connection.n, err := conn.Read(buf)if err != nil {log.Fatal(err)}// Echo the data back to the connection._, err = conn.Write(buf[:n])if err != nil {log.Fatal(err)}}(conn)}
}

运行go build .,生成可执行文件。然后利用netcat测试echo服务,使用-U选项指定socket文件,连接后可以发送和接收文件。

$ echo "File Socket Demo." | nc -U /tmp/echo.sock
File Socket Demo.

使用Unix域socket实现http服务器

unix域socket也可以实现http服务,使用server.Serve和net.Listener函数:

package main
import (...)const socketPath = "/tmp/httpecho.sock"
func main() {// Create a Unix domain socket and listen for incoming connections.socket, err := net.Listen("unix", socketPath)if err != nil {panic(err)}// Cleanup the sockfile.c := make(chan os.Signal, 1)signal.Notify(c, os.Interrupt, syscall.SIGTERM)go func() {<-cos.Remove(socketPath)os.Exit(1)}()m := http.NewServeMux()m.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {w.Write([]byte("Hello golang network developer!"))})server := http.Server{Handler: m,}if err := server.Serve(socket); err != nil {log.Fatal(err)}
}

使用下面命令进行测试:

$ curl -s -N --unix-socket /tmp/httpecho.sock http://localhost/
Hello golang network developer!

使用unix域socket实现http服务的优势为,增强安全性、提升性能,容易使用,对于必须在同一台机器进程间通信的场景,这些优点使得HTTP服务器实现更加高效、可靠、可扩展。

总结

安全性

unix域socket和网络socket在安全性方面有差异。unix域比网络更安全,因为它不需要对外暴露给网络,进行在同一台服务器上的进程间通信。unix域仅使用文件系统权限去控制访问,指定用户和组创建socket文件并仅有权限的用户和组才能访问进程。这意味着仅收取进程能连接至socket和交互数据。

相反,网络socket暴露在网络上并任何机器都可以连接并访问,很容易受到恶意用户(如黑客和恶意软件)的攻击。网络socket使用tcp/udp协议,这些协议有他们自己安全机制,如加密和认证。但这些机制不足以防御各种类型的攻击,网络socket总是存在威胁。

如何选择

具体选择哪种类型socket,主要考虑的是应用程序需求和约束。Unix域套接字速度更快,效率更高,但仅限于同一机器上进程之间的通信。网络套接字更通用,但需更多开销,并可能受到网络延迟和网络攻击的影响。一般来说,Unix域套接字适用于同一机器上的IPC和服务之间的通信,而网络套接字适用于网络上的客户机-服务器通信。

当您需要在同一主机上的进程之间通信时,应该选择Unix域套接字而不是网络套接字。Unix域套接字在同一主机上的进程之间提供了安全有效的通信通道,适用于进程需要频繁或实时交换数据的场景。例如,假设在K8s的pod中有两个容器,它们必须尽可能快地相互通信!

综上所述,Unix域套接字和网络套接字是Golang中两种重要的套接字类型,用于不同的目的和场景。理解这些套接字类型之间的差异和权衡对于在Golang中设计和实现高效可靠的网络应用程序至关重要。请记住,使用unix套接字的进程之间的通信仅由内核处理,而在网络套接字中,通信涉及内核、网络堆栈和网络硬件。


http://www.ppmy.cn/news/12863.html

相关文章

二叉树的应用——哈夫曼树

哈夫曼树与哈夫曼编码 1.树的带权路径长 百分制成绩转五级制的算法流程图&#xff08;A/B/C/D/E的人数分别为6/18/21/36/19&#xff09;带权路径长 路经长 x 权重 树的带权路经长&#xff1a;所有叶结点的带权路径长度之和。 例如&#xff1a; &#xff08;a&#xff09;图…

表达式求值【NOIP2013普及组】

表达式求值【NOIP2013普及组】 给定一个只包含加法和乘法的算术表达式&#xff0c;请你编程计算表达式的值。 输入输出格式 输入格式&#xff1a; 输入仅有一行&#xff0c;为需要你计算的表达式&#xff0c;表达式中只包含数字、加法运算符“”和乘法运算符“*”&#xff…

一、构建自己的图像分类数据集(Datawhale组队学习)

文章目录安装配置环境图像采集采集函数爬取一类图片爬取多类图片一些参考类别的关键词制作图像分类数据集的注意事项删除多余文件删除系统自动生成的多余文件删除gif格式的图像文件删除非三通道的图像统计图像尺寸、比例分布采用的数据集统计数据集的基本信息可视化图像尺寸分布…

使用隐马尔科夫模型实现分词

文章目录算法概述算法实现参考结论参考资料参考链接算法概述 分词算法常用的方法是基于统计的机器学习算法。可以使用 隐马尔科夫模型&#xff08;HMM&#xff09; 来实现分词。 隐马尔科夫模型的基本思想是假设一个序列是由一个隐藏的马尔科夫链生成的&#xff0c;而每个状态…

Chrome V3版开发教程使用Vue 3.x+Ant构建项目

简介 ​ Google在2023年将会遗弃V2版本&#xff0c;而目前在CSDN平台上的大部分Chrome插件的开发教程都是基于V2版本的&#xff0c;V3版本和V2的版本上还是有很大的区别&#xff0c;就比如manifest.json中的写法差距就很大&#xff0c;所以对于即将要开发Chrome插件的小伙伴来…

操作系统之光--鸿蒙

鸿蒙是什么&#xff1f;鸿蒙包含Openharmony和harmonyOS。Openharmony是华为向开放原子开源基金会捐赠了鸿蒙开源部分的代码&#xff0c;归属于开放原子开源基金会。HarmonyOS是基于Openharmony的商业发行版本。目前大家华为手机上运行就是它。鸿蒙能做什么&#xff1f;很明显&…

数据结构设计--《五子棋》对弈程序

手敲800多行代码,搞了6个小时,终于写完了五子棋博弈问题,艰难!(以下纯属个人思路,仅供参考,创作不易,禁止搬运) 希望对大家有帮助。 1.课题要求 还记得我们在第一章 见过的“人机对弈”那个例子吗?现在就请你利用自己所学的知识,设计一一个“ 五子棋”对弈程序吧。注意:…

【青训营】Go的依赖管理

Go的依赖管理 本节内容来自于&#xff1a;字节跳动青年训练营第五届 后端组 1.什么是依赖 实际开发的工程需要使用许多第三方库&#xff0c;这能够使得我们站在巨人的肩膀上&#xff0c;使用第三方库中封装好的函数&#xff0c;可以大大方便我们的程序开发&#xff0c;第三方…