Python3 UNIX domain sockets使用代码实现

一、说明

背景一:大学的时候学网络编程,经常看到说socket有AF_UNIX、AF_INET和AF_INET6三个协议族,AF_UNIX一般不用、AF_INET是IPv4的、AF_INET6是IPv6的。基于这种说教一直以来写网络编程,上来协议族就写AF_INET,AF_UNIX是什么怎么用一直没深究。

背景二:毕业后多接触Linux,也经常用netstat看端口监听情况,在较长一段时间内也不懂“netstat -ltnp”、"netstat -unp",上来就是“netstat -anp”。这样导致的问题就是在最后总是有“Active UNIX domain sockets”一项,而且经常占很长的一个版面,要往前拉很久才能看到前面的tcp和udp。

背景三:今天早上看《Linux内核源代码情景分析》的进程间通信章节,发现AF_UNIX和UNIX domain sockets竟是一个东西,同时解决了两个困惑,真想击节称叹。

二、使用代码实现

2.1 服务端示例代码

import socket

class SocketServer:
    def __init__(self):
        # 常规tcp监听写法
        # server_address = (‘127.0.0.1‘, 9999)
        # socket_family = socket.AF_INET
        # socket_type = socket.SOCK_STREAM

        # unix domain sockets 监听写法
        server_address = ‘/tmp/uds_socket‘
        socket_family = socket.AF_UNIX
        socket_type = socket.SOCK_STREAM

        # 其他代码完全一样
        self.sock = socket.socket(socket_family, socket_type)
        self.sock.bind(server_address)
        self.sock.listen(1)
        print(f"listening on ‘{server_address}‘.")
        pass

    def wait_and_deal_client_connect(self):
        while True:
            connection, client_address = self.sock.accept()
            data = connection.recv(1024)
            print(f"recv data from client ‘{client_address}‘: {data.decode()}")
            connection.sendall("hello client".encode())

    def __del__(self):
        self.sock.close()

if __name__ == "__main__":
    socket_server_obj = SocketServer()
    socket_server_obj.wait_and_deal_client_connect()

2.2 客户端示例代码

import socket

class SocketClient:
    def __init__(self):
        pass

    def connect_to_server(self):
        # 常规tcp连接写法
        # server_address = (‘127.0.0.1‘, 9999)
        # socket_family = socket.AF_INET
        # socket_type = socket.SOCK_STREAM

        # unix domain sockets 连接写法
        server_address = ‘/tmp/uds_socket‘
        socket_family = socket.AF_UNIX
        socket_type = socket.SOCK_STREAM

        # 其他代码完全一样
        sock = socket.socket(socket_family, socket_type)
        sock.connect(server_address)
        sock.sendall("hello server".encode())
        data = sock.recv(1024)
        print(f"recv data from server ‘{server_address}‘: {data.decode()}")
        sock.close()

if __name__ == "__main__":
    socket_client_obj = SocketClient()
    socket_client_obj.connect_to_server()

三、运行结果

3.1 运行步骤

第一步:启动服务端

第二步:运行客户端

第三步:再回头看服务端输出

可以看到客户端与服务端成功通过UNIX domain sockets进行通信。

3.2 其他的佐证

上边的截图确实能说明服务端与客户端能够进行通信,为了更有说服力地说明使用的就是UNIX domain sockets本身,我们可以提供其他一些佐证。

使用netstat查看是监听存在:

查看指定的/tmp/uds_socket存在,且是一个大小为0的文件:

四、关于进程通信的其他一些问题

4.1 关于UNIX domain sockets的说明

在Unix的发展史中,AT&T和BSD是两大主力。在进程间通信方面两者着重点各有不同。

AT&T保留传统的Unix IPC写法,着重对其实现细节加以打磨,形成了SysV IPC通信机制;而BSD则直接将机器内部进程间通信视为不同机器进程间通信的一个特例,将两者在写法上都统一为socket的形式。

由于socket在单机实现上与SysV IPC并没有很大差别,而又与跨机器进程间通信的写法相统一,所以socket成为了更常用的通信形式。

另外这里要注意,socket在单机实现上与SysV IPC并没有很大差别,这就意味着socket单机实现上与socket跨机器实现上是有较大差别的,最直接的一点是由于是在单台机器上报文的传递并不需要复杂的TCP等协议去保证其顺序性,所以从性能等方面讲AF_UNIX会优于AF_INET。

4.2 为什么现在的框架监听一堆端口

在上家公司测试基于spring boot开发的一套系统时,发现spring boot监听了一堆的端口,当时问领导说进程间通信使用管道不就好了吗为什么要监听一堆端口呢,他说并不是现在大多数也都通过socket的方式进行通信。

现在想来他的说法也不够清晰准确。进程间通信,旧的方法是管道、新的方法是UNIX domain sockets(AF_UNIX),spring boot等使用AF_INET这种成本更高的的形式一是为了方便地使用http二是为了方便分布式。

参考:

https://pymotw.com/2/socket/uds.html

https://docs.python.org/3/library/socket.html

原文地址:https://www.cnblogs.com/lsdb/p/12191095.html

时间: 2024-10-15 12:40:15

Python3 UNIX domain sockets使用代码实现的相关文章

Unix domain sockets

#server: SERVER_PATH = "/tmp/python_unix_socket_server" def run_unix_domain_socket_server(): if os.path.exists(SERVER_PATH): os.remove(SERVER_PATH) print('starting unix domain socket server.') # #UNIX 无连接的socket(类型 SOCK_DGRAM) sever=socket.socke

由一个简单需求到Linux环境下的syslog、unix domain socket

本文记录了因为一个简单的日志需求,继而对linux环境下syslog.rsyslog.unix domain socket的学习.本文关注使用层面,并不涉及rsyslog的实现原理,感兴趣的读者可以参考rsyslog官网.另外,本文实验的环境实在debian8,如果是其他linux发行版本或者debian的其他版本,可能会稍微有些差异. 需求: 工作中有一个在Linux(debian8)环境下运行的服务器程序,用python语言实现,代码中有不同优先级的日志需要记录,开发的时候都是使用pytho

ndk学习16: unix domain socket

一.UNIX Domain Socket 概念: UNIX Domain Socket是在socket架构上发展起来的用于同一台主机的进程间通讯(IPC) 特点: 1. 它不需要经过网络协议栈,不需要打包拆包.计算校验和.维护序号和应答等 2. 只是将应用层数据从一个进程拷贝到另一个进程. 工作模式: SOCK_DGRAM     类似于UDP SOCK_STREAM    类似于TCP 用途: UNIX Domain Socket可用于两个没有亲缘关系的进程,是全双工的,是目前使用最广泛的IP

【转】PHP实现系统编程(四)--- 本地套接字(Unix Domain Socket)

原文:http://blog.csdn.net/zhang197093/article/details/78143687?locationNum=6&fps=1 -------------------------------------------------------------------------------------------------------------------------------------------------------- Socket API一开始是为了

[dev][socket] unix domain socket删除socket文件

问题 在使用unix domain socket的时候,bind之后,会在本地路径里 产生一个与path对应的socket文件. 如何正确的在用完socket之后,对其销毁呢? 方案 使用 unlink()函数手工删除. 见: https://stackoverflow.com/questions/34873151/how-can-i-delete-a-unix-domain-socket-file-when-i-exit-my-application syslogd的代码里就是这样干的: ht

UNIX域套接字(unix domain)

UNIX域套接字用于在同一台机器上运行的进程之间的通信. UNIX域套接字提供流和数据报两种接口. 创建一对非命名的.相互连接的UNIX域套接字. socketpair 1.命名UNIX域套接字 1)套接字地址格式,在linux下如下所示 struct sockaddr_un { sa_family_t sun_family; char sun_path[108]; } 绑定该地址: #include <stdlib.h> #include <string.h> #include

unix domain socket示例一(SOCK_DGRAM)

unix domain socket 是IPC通信的一种方式,可用于与管理进程间通信,同时由和网络socket统一,所以很好管理,使用还是比较多.现举个例子: server.c 1 #include <stdio.h> 2 #include <string.h> 3 #include <unistd.h> 4 #include <stdlib.h> 5 #include <sys/types.h> 6 #include <sys/socke

redis性能测试tcp socket and unix domain

UNIX Domain Socket IPC socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机制,就是UNIX Domain Socket.虽然网络socket也可用于同一台主机的进程间通讯(通过loopback地址127.0.0.1),但是UNIX Domain Socket用于IPC更有效率:不需要经过网络协议栈,不需要打包拆包.计算校验和.维护序号和应答等,只是将应用层数据从一个进程拷贝到另一个进程.UNIX域套接字与TCP套接字相比较,在同一台主

UNIX Domain Socket IPC

目录 目录 概述 socket函数使用 struct sockaddr_un socket bind listen accept connect Socket IPC 实例 server client 运行结果 概述 socket API原本是为网络通讯设计的,但是后来在socket的框架上发展出一种IPC机制,就是UNIX Domain Socket. 虽然网络socket也可用于同一台主机的进程间通讯(通过loopback地址127.0.0.1),但是UNIX Domain Socket用于