【socket】关于Unix域套接字(Unix Domain Socket)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了【socket】关于Unix域套接字(Unix Domain Socket)相关的知识,希望对你有一定的参考价值。
参考技术A 现实世界中两个人进行信息交流的整个过程被称作一次通信(Communication),通信的双方被称为端点(Endpoint)。工具通讯环境的不同,端点之间可以选择不同的工具进行通信,距离近可以直接对话,距离远可以选择打电话、微信聊天。这些工具就被称为 Socket。
同理,在计算机中也有类似的概念:
在 Unix 中,一次通信由两个端点组成,例如 HTTP 服务端和 HTTP 客户端。
端点之间想要通信,必须借助某些工具,Unix 中端点之间使用 Socket 来进行通信。
Socket 原本是为网络通信而设计的,但后来在 Socket 的框架上发展出一种 IPC 机制,就是 UDS。
Unix Domain Socket(UDS,Unix 域套接字),它还有另一个名字叫 IPC(inter-process communication,进程间通信)。
使用 UDS 的好处显而易见:不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是将应用层数据从一个进程拷贝到另一个进程。这是因为,IPC 机制本质上是可靠的通讯,而网络协议是为不可靠的通讯设计的。
UDS 与网络 Socket 最明显的区别在于,网络 Socket 地址是 IP 地址加端口号,而 UDS 的地址是一个 Socket 类型的文件在文件系统中的路径,一般名字以 .sock 结尾。
这个 Socket 文件可以被系统进程引用,两个进程可以同时打开一个 UDS 进行通信,而且这种通信方式只会发生在系统内核里,不会在网络上进行传播。
mysql 在本地可以通过 socket 方式连接。
在本地登录时,如果 my.cnf 配置文件中的 [client] 部分没有指定 socket 文件路径,mysql 默认会去寻找 /tmp/mysql.sock(编译装)或 /var/lib/mysql/mysql.sock(rpm安装),所以如果 mysqld 服务启动的时候,生成的 socket 文件不是默认路径的话,登陆可能会报错(ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock')。
其实 [mysqld] 部分及 [client] 部分都配置具体路径可避免此问题,也可以在 tmp 路径下建立软连接,如:ln -s /pah/to/mysql.sock /tmp/mysql.sock 。
同样的,socket 文件目录权限要对 mysql 系统用户放开。
在docker官方文档docker-engine中,介绍了三种访问docker Remote API的方式,分别是unix套接字文件、tcp监听端口和fd文件描述符。
MySQL中的pid与socket是什么?
https://mp.weixin.qq.com/s/MehZ8GeRD9SBm8PxfGugRw
网络协议之:socket协议详解之Unix domain Socket
http://www.flydean.com/17-unix-domain-socket
https://mp.weixin.qq.com/s/4RwASqJu3Vc_suslKSbBkw
如何给UNIX域Socket套接字抓包?
https://mp.weixin.qq.com/s/SrV9_RouBJtZaUgG4WlamQ
Unix域套接字(Unix Domain Socket)介绍
https://mp.weixin.qq.com/s/psmAL216huaqytwrbcoIMw
关于/var/run/docker.sock文件的理解
https://cloud.tencent.com/developer/article/1454335
Daemon socket option
https://docs.docker.com/engine/reference/commandline/dockerd/#description
使用 Unix Domain Socket 与上游集群通信
https://mp.weixin.qq.com/s/5i_y1O7bSafAW7I51S7N8w
彻底搞懂文件描述符fd
https://www.itqiankun.com/article/file-fd
可以在Unix域套接字上使用SO_REUSEPORT吗?
Linux内核> = 3.9允许通过设置SO_REUSEPORT
来共享内核负载平衡进程之间的套接字:http://lwn.net/Articles/542629/
如何将它用于AF_UNIX
类型的插座?
看来,它只适用于TCP,而不适用于Unix域套接字。
这是一个Python测试程序:
import os
import socket
if not hasattr(socket, 'SO_REUSEPORT'):
socket.SO_REUSEPORT = 15
if True:
# using TCP sockets
# works. test with: "echo data | nc localhost 8888"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
s.bind(('', 8888))
else:
# using Unix domain sockets
# does NOT work. test with: "echo data | nc -U /tmp/socket1"
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
try:
os.unlink("/tmp/socket1")
except:
pass
s.bind("/tmp/socket1")
s.listen(1)
while True:
conn, addr = s.accept()
print('Connected to {}'.format(os.getpid()))
data = conn.recv(1024)
conn.send(data)
conn.close()
启动2个实例,并通过多次运行以下测试:
- 用于TCP的
echo data | nc localhost 8888
echo data | nc -U /tmp/socket1
用于Unix域套接字
使用TCP时,传入的客户端将与两台服务器保持平衡。使用Unix域套接字,传入的客户端都连接到最后启动的服务器。
答案
这个特定的内核补丁在这里记录:
从修补文件列表中可以看出,补丁仅影响了net/ipv4
和net/ipv6
套接字。 Unix域套接字在net/unix
中实现。所以,答案是:不,SO_REUSEPORT不适用于AF_UNIX类型的套接字。
另一答案
一个小补丁,在UNIX套接字SO_REUSEPORT
上增加了对was posted的支持,但是被拒绝了。但是这个补丁并没有在多个套接字上实现负载均衡,如果套接字文件已经存在,它只会导致bind()
不会失败。
这个用例被认为是
从用户的角度来看,这是一个非常奇怪的角落案例
因此,仍有可能通过SO_REUSEPORT
实现UNIX套接字负载平衡的不同补丁将被接受。
以上是关于【socket】关于Unix域套接字(Unix Domain Socket)的主要内容,如果未能解决你的问题,请参考以下文章