现实世界中两个人进行信息交流的整个过程被称作一次通信 (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 系统用户放开。
$ mysq -u root --socket=/path/to/mysql.sock
$ mysql --help | grep socket
-S, --socket=name
The socket file to use for connection.
The buffer size for TCP/IP and socket communication.
在 docker 官方文档 docker-engine 中, 介绍了三种访问 docker Remote API 的方式, 分别是 unix 套接字文件、tcp 监听端口和 fd 文件描述符。
# cat /var/systemd/system/docker.service
ExecStart= /usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
The feature was added in curl 7.40
.
curl --unix-socket /var/run/docker.sock http:/images/json
Another example:
curl --no-buffer -XGET --unix-socket /docker.sock http:/events
Which specifies the GET
explicitly (rather than assumed). And will not buffer (for tail -f
realtime update).
(The first Ubuntu release to ship with curl 7.40 or newer was 15.10).
cURL 7.50
and up requires a valid URL to be provided, including a hostname, so to run the above examples with cURL 7.50
, a “dummy” hostname has to be added, for example:
curl --unix-socket /var/run/docker.sock http://localhost/images/json
and
curl --no-buffer -XGET --unix-socket /docker.sock http://localhost/events