Python_unix domain socket(域套接字)

业务上需要实现romd与superd通信,采用的通信协议是:unix domain socket

简介

  • Unix Domain Socket通常称为 【unix域套接口】 或 【本地套接口】,它用于位于同一台机器(操作系统)的进程间通信。它已经被纳入POSIX Operating Systems标准。
    它支持以下三种方式数据传输:
    (1) 可靠的字节流传输(SOCK_STREAM, 对应TCP);
    (2) 无序、不可靠的数据包传输(SOCK_DGRAM,对应UDP)。
    (3)有序、可靠的数据包传输(SOCK_SEQPACKET)原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。
    (4)socket.SOCK_RDM 是一种可靠的UDP形式,即保证交付数据报但不保证顺序。SOCK_RDM用来提供对原始协议的低级访问,在需要执行某些特殊操作时使用,如发送ICMP报文。SOCK_RDM通常仅限于高级用户或管理员运行的程序使用。
    (5)socket.SOCK_SEQPACKET 可靠的连续数据包服务
  • Unix Domain Socket 的通信基于操作系统内核的,使用文件系统作为地址命名空间(address name space)。
  • socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机制,就是UNIXDomain Socket。虽然网络socket也可用于同一台主机的进程间通讯(通过loopback地址127.0.0.1),但是UNIX Domain Socket用于IPC更有效率:不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是将应用层数据从一个进程拷贝到另一个进程。这是因为,IPC机制本质上是可靠的通讯,而网络协议是为不可靠的通讯设计的。UNIX Domain Socket也提供面向流和面向数据包两种API接口,类似于TCP和UDP,但是面向消息的UNIX Domain Socket也是可靠的,消息既不会丢失也不会顺序错乱。
  • UNIX Domain Socket是全双工的,API接口语义丰富,相比其它IPC机制有明显的优越性,目前已成为使用最广泛的IPC机制,比如X Window服务器和GUI程序之间就是通过UNIX Domain Socket通讯的。
  • 使用UNIX Domain Socket的过程和网络socket十分相似,也要先调用socket()创建一个socket文件描述符,address family指定为AF_UNIX,type可以选择SOCK_DGRAM或SOCK_STREAM,protocol参数仍然指定为0即可。
  • UNIX Domain Socket与网络socket编程最明显的不同在于地址格式不同,用结构体sockaddr_un表示,网络编程的socket地址是IP地址加端口号,而UNIX Domain Socket的地址是一个socket类型的文件在文件系统中的路径,这个socket文件由bind()调用创建,如果调用bind()时该文件已存在,则bind()错误返回。

代码:

以下代码主要讲2种域套接字的通信方式

  • tcp形式的套接字
# server端
import socket
import sys 
import os

serverAddr = './uds_socket' # 套接字存放路径及名称

def serverSocket():
        #create sockert
        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)# unix套接字,tcp通信方式
        if sock < 0:
                print >> sys.stderr, 'socket error'
        # bind to a file
        if os.path.exists(serverAddr):
                os.unlink(serverAddr)# 如果套接字存在,则删除
        if sock.bind(serverAddr): #绑定套接字文件,绑定成功后,会在指定路径下生成一个域套接字文件。
                print >> sys.stderr, 'socket.bind error'

        #listen
        if sock.listen(5): #最多监听5个客户端
                print >> sys.stderr, 'socket.listen error'

        while True:
                print >> sys.stderr, 'waiting for connecting'
                #waiting for client connecting
                conn, clientAddr = sock.accept() #如果监听到客户端连接,则调用accept接收这个连接并同时新建一个socket来和客户进行通信
                try:
                        # receive data 
                        # send data to client
                        while True:
                                data = conn.recv(100)#接收100个字节长度的数据
                                if data:
                                        print >> sys.stderr, 'received "%s"' %data
                                        conn.sendall(data)#发送数据
                                else:
                                        break
               except Exception as e :
                        print(e)

if __name__ == "__main__":
        serverSocket()
# client端
import socket
import sys 
import os

serverAddr = './uds_socket' #注意想要跟谁通信就绑定谁的套接字文件

def clientSocket():
        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        if sock < 0:
                print >> sys.stderr, 'socket error'

        try:
                sock.connect(serverAddr)
        except socket.error, msg:
                print >> sys.stderr, "exception"
                print >> sys.stderr, msg 
                sys.exit(1)

        message = 'this is the message'
        sock.sendall(message)

        amountRecv = 0 
        amountSnd = len(message)

        while amountRecv < amountSnd:
                data = sock.recv(100)
                amountRecv += len(data)
                print >> sys.stderr, 'received "%s"' %data
        sock.close()

if __name__ == "__main__":
        clientSocket()
  • udp形式的套接字
    注意:udp形式的套接字与tcp最大的不同就是:
    • 它没有server端、client端的区分,意思就是双方各自是独立服务,A想给B发,那么就直接往指定的B的套接字文件发送就可以了
    • 不区分主次,自然也就不需要准入了accept
# coding:utf-8
__author__ = 'xcma'
import socket
import sys
import os

aAddr = './a.sock' # 套接字存放路径及名称
bAddr = './b.sock'
def serverSocket():
        #create sockert
        sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)# @这里不同   unix套接字,udp通信方式
        if sock < 0:
                print >> sys.stderr, 'socket error'
        # bind to a file
        if os.path.exists(aAddr):
                os.unlink(aAddr)# 如果套接字存在,则删除
        if sock.bind(aAddr): #删除后,绑定套接字文件
                print >> sys.stderr, 'socket.bind error'

        while True:
                print >> sys.stderr, 'waiting for connecting'
                try:
                        # receive data
                        # send data to client
                    while True:
                            data = sock.recv(100)#接收100个字节长度的数据
                            if data:
                                    print >> sys.stderr, 'received "%s"' %data
                                    sock.sendall(data,bAddr)# @ 这里不同 发送数据
                            else:
                                    break
                except Exception as e:
                    print(e)
if __name__ == "__main__":
        serverSocket()

这样如果需要UDP方式,双方通信,各自只需要绑定自己的域套接字文件,然后发送数据的时候指向目标的套接字文件就可以了

总结:

以上只是简单示例,实际应用中保准不能这么用,会显得比较没有层次,而且不容易维护,总的来说用起来还是比较简单的,遇到问题,也比较好查。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容

  • 一 、Socket 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个 Socket。S...
    空白Null阅读 1,750评论 1 9
  • Socket创建函数 socket.socket(socket_family, socket_type, prot...
    JianMing阅读 6,008评论 1 13
  • 一、 概述UNIX Domain Socket是在socket架构上发展起来的用于同一台主机的进程间通讯(IPC)...
    chandarlee阅读 6,781评论 0 51
  • 什么是TCP/IP、UDP? TCP/IP(Transmission Control Protocol/Inter...
    liuboxx1阅读 984评论 0 1
  • 姥爷(眼睛不好)吃完一碗饭后,要去旁边的盆里盛饭。这时姥姥说,别上这里盛,这是给狗吃的。
    风铃大姑娘阅读 128评论 0 0