Python_unix domain socket(域套接字)

業(yè)務(wù)上需要實(shí)現(xiàn)romd與superd通信,采用的通信協(xié)議是:unix domain socket

簡(jiǎn)介

  • Unix Domain Socket通常稱(chēng)為 【unix域套接口】 或 【本地套接口】,它用于位于同一臺(tái)機(jī)器(操作系統(tǒng))的進(jìn)程間通信。它已經(jīng)被納入POSIX Operating Systems標(biāo)準(zhǔn)。
    它支持以下三種方式數(shù)據(jù)傳輸:
    (1) 可靠的字節(jié)流傳輸(SOCK_STREAM, 對(duì)應(yīng)TCP);
    (2) 無(wú)序、不可靠的數(shù)據(jù)包傳輸(SOCK_DGRAM,對(duì)應(yīng)UDP)。
    (3)有序、可靠的數(shù)據(jù)包傳輸(SOCK_SEQPACKET)原始套接字,普通的套接字無(wú)法處理ICMP、IGMP等網(wǎng)絡(luò)報(bào)文,而SOCK_RAW可以;其次,SOCK_RAW也可以處理特殊的IPv4報(bào)文;此外,利用原始套接字,可以通過(guò)IP_HDRINCL套接字選項(xiàng)由用戶(hù)構(gòu)造IP頭。
    (4)socket.SOCK_RDM 是一種可靠的UDP形式,即保證交付數(shù)據(jù)報(bào)但不保證順序。SOCK_RDM用來(lái)提供對(duì)原始協(xié)議的低級(jí)訪問(wèn),在需要執(zhí)行某些特殊操作時(shí)使用,如發(fā)送ICMP報(bào)文。SOCK_RDM通常僅限于高級(jí)用戶(hù)或管理員運(yùn)行的程序使用。
    (5)socket.SOCK_SEQPACKET 可靠的連續(xù)數(shù)據(jù)包服務(wù)
  • Unix Domain Socket 的通信基于操作系統(tǒng)內(nèi)核的,使用文件系統(tǒng)作為地址命名空間(address name space)。
  • socket API原本是為網(wǎng)絡(luò)通訊設(shè)計(jì)的,但后來(lái)在socket的框架上發(fā)展出一種IPC機(jī)制,就是UNIXDomain Socket。雖然網(wǎng)絡(luò)socket也可用于同一臺(tái)主機(jī)的進(jìn)程間通訊(通過(guò)loopback地址127.0.0.1),但是UNIX Domain Socket用于IPC更有效率:不需要經(jīng)過(guò)網(wǎng)絡(luò)協(xié)議棧,不需要打包拆包、計(jì)算校驗(yàn)和、維護(hù)序號(hào)和應(yīng)答等,只是將應(yīng)用層數(shù)據(jù)從一個(gè)進(jìn)程拷貝到另一個(gè)進(jìn)程。這是因?yàn)椋琁PC機(jī)制本質(zhì)上是可靠的通訊,而網(wǎng)絡(luò)協(xié)議是為不可靠的通訊設(shè)計(jì)的。UNIX Domain Socket也提供面向流和面向數(shù)據(jù)包兩種API接口,類(lèi)似于TCP和UDP,但是面向消息的UNIX Domain Socket也是可靠的,消息既不會(huì)丟失也不會(huì)順序錯(cuò)亂。
  • UNIX Domain Socket是全雙工的,API接口語(yǔ)義豐富,相比其它IPC機(jī)制有明顯的優(yōu)越性,目前已成為使用最廣泛的IPC機(jī)制,比如X Window服務(wù)器和GUI程序之間就是通過(guò)UNIX Domain Socket通訊的。
  • 使用UNIX Domain Socket的過(guò)程和網(wǎng)絡(luò)socket十分相似,也要先調(diào)用socket()創(chuàng)建一個(gè)socket文件描述符,address family指定為AF_UNIX,type可以選擇SOCK_DGRAM或SOCK_STREAM,protocol參數(shù)仍然指定為0即可。
  • UNIX Domain Socket與網(wǎng)絡(luò)socket編程最明顯的不同在于地址格式不同,用結(jié)構(gòu)體sockaddr_un表示,網(wǎng)絡(luò)編程的socket地址是IP地址加端口號(hào),而UNIX Domain Socket的地址是一個(gè)socket類(lèi)型的文件在文件系統(tǒng)中的路徑,這個(gè)socket文件由bind()調(diào)用創(chuàng)建,如果調(diào)用bind()時(shí)該文件已存在,則bind()錯(cuò)誤返回。

代碼:

以下代碼主要講2種域套接字的通信方式

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

serverAddr = './uds_socket' # 套接字存放路徑及名稱(chēng)

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): #綁定套接字文件,綁定成功后,會(huì)在指定路徑下生成一個(gè)域套接字文件。
                print >> sys.stderr, 'socket.bind error'

        #listen
        if sock.listen(5): #最多監(jiān)聽(tīng)5個(gè)客戶(hù)端
                print >> sys.stderr, 'socket.listen error'

        while True:
                print >> sys.stderr, 'waiting for connecting'
                #waiting for client connecting
                conn, clientAddr = sock.accept() #如果監(jiān)聽(tīng)到客戶(hù)端連接,則調(diào)用accept接收這個(gè)連接并同時(shí)新建一個(gè)socket來(lái)和客戶(hù)進(jìn)行通信
                try:
                        # receive data 
                        # send data to client
                        while True:
                                data = conn.recv(100)#接收100個(gè)字節(jié)長(zhǎng)度的數(shù)據(jù)
                                if data:
                                        print >> sys.stderr, 'received "%s"' %data
                                        conn.sendall(data)#發(fā)送數(shù)據(jù)
                                else:
                                        break
               except Exception as e :
                        print(e)

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

serverAddr = './uds_socket' #注意想要跟誰(shuí)通信就綁定誰(shuí)的套接字文件

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最大的不同就是:
    • 它沒(méi)有server端、client端的區(qū)分,意思就是雙方各自是獨(dú)立服務(wù),A想給B發(fā),那么就直接往指定的B的套接字文件發(fā)送就可以了
    • 不區(qū)分主次,自然也就不需要準(zhǔn)入了accept
# coding:utf-8
__author__ = 'xcma'
import socket
import sys
import os

aAddr = './a.sock' # 套接字存放路徑及名稱(chēng)
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個(gè)字節(jié)長(zhǎng)度的數(shù)據(jù)
                            if data:
                                    print >> sys.stderr, 'received "%s"' %data
                                    sock.sendall(data,bAddr)# @ 這里不同 發(fā)送數(shù)據(jù)
                            else:
                                    break
                except Exception as e:
                    print(e)
if __name__ == "__main__":
        serverSocket()

這樣如果需要UDP方式,雙方通信,各自只需要綁定自己的域套接字文件,然后發(fā)送數(shù)據(jù)的時(shí)候指向目標(biāo)的套接字文件就可以了

總結(jié):

以上只是簡(jiǎn)單示例,實(shí)際應(yīng)用中保準(zhǔn)不能這么用,會(huì)顯得比較沒(méi)有層次,而且不容易維護(hù),總的來(lái)說(shuō)用起來(lái)還是比較簡(jiǎn)單的,遇到問(wèn)題,也比較好查。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一 、Socket 網(wǎng)絡(luò)上的兩個(gè)程序通過(guò)一個(gè)雙向的通信連接實(shí)現(xiàn)數(shù)據(jù)的交換,這個(gè)連接的一端稱(chēng)為一個(gè) Socket。S...
    空白Null閱讀 1,882評(píng)論 1 9
  • Socket創(chuàng)建函數(shù) socket.socket(socket_family, socket_type, prot...
    JianMing閱讀 6,091評(píng)論 1 13
  • 一、 概述UNIX Domain Socket是在socket架構(gòu)上發(fā)展起來(lái)的用于同一臺(tái)主機(jī)的進(jìn)程間通訊(IPC)...
    chandarlee閱讀 7,012評(píng)論 0 51
  • 什么是TCP/IP、UDP? TCP/IP(Transmission Control Protocol/Inter...
    liuboxx1閱讀 1,053評(píng)論 0 1
  • 姥爺(眼睛不好)吃完一碗飯后,要去旁邊的盆里盛飯。這時(shí)姥姥說(shuō),別上這里盛,這是給狗吃的。
    風(fēng)鈴大姑娘閱讀 152評(píng)論 0 0

友情鏈接更多精彩內(nèi)容