python3 進程間通信之socket.socketpair()
socket.socketpair()是什么鬼東西?
socket.socketpair()函數僅返回兩個已經連接的套接字對象,參數和socket.socket()里的參數一樣的用法。
socket.socketpair()可以理解為 創建了兩個socket, 比喻為一個server的 socket,一個client的socket,這兩個socket是已經connected連接狀態
socket.socketpair()是全雙工模式,也就是每個socket都能收發,比喻為server.send--->client.recv,和 client.send--->server.recv
socket.socketpair()默認是創建unix套接字
用例子理解:
1.單個進程中的 socket.socketpair
a,b=socket.socketpair() print(a) print(b) a.send(b'hello') brecv=b.recv(1024) print('b recv',brecv.decode()) b.send('你好啊'.encode()) arecv=a.recv(1024) print('a recv',arecv.decode())
結果:
<socket.socket fd=4, family=AddressFamily.AF_UNIX, type=SocketKind.SOCK_STREAM, proto=0> <socket.socket fd=5, family=AddressFamily.AF_UNIX, type=SocketKind.SOCK_STREAM, proto=0> b recv hello a recv 你好啊
2.多個進程os.fork()中的 socket.socketpair
os.fork 參考url:https://www.cnblogs.com/lijinlei521/p/12699388.html
os.fork 就是克隆進程,在主進程中創建子進程,並復制主進程所有內存地址到子進程中,並一起執行fork之后的代碼塊,父子進程會返回不同的pid號 來區別是主進程(主進程返回子進程pid)還是子進程(子進程返回pid 號0)
import os import socket socket1,socket2=socket.socketpair() pid=os.fork() if pid==0: print('子進程') print('子進程-',socket1,id(socket1)) print('子進程-',socket2,id(socket2)) else: print('父進程') print('父進程-',socket1,id(socket1)) print('父進程-',socket2,id(socket2))
結果:
父進程 父進程- <socket.socket fd=4, family=AddressFamily.AF_UNIX, type=SocketKind.SOCK_STREAM, proto=0> 4334200680 父進程- <socket.socket fd=5, family=AddressFamily.AF_UNIX, type=SocketKind.SOCK_STREAM, proto=0> 4334200776 子進程 子進程- <socket.socket fd=4, family=AddressFamily.AF_UNIX, type=SocketKind.SOCK_STREAM, proto=0> 4334200680 子進程- <socket.socket fd=5, family=AddressFamily.AF_UNIX, type=SocketKind.SOCK_STREAM, proto=0> 4334200776
說明:
1.os.fork() 復制了主進程所有內存地址到子進程,所以 子進程和父進程現在都有兩個一樣(id結果一樣)的socket (socket1,socket2)
2.所以可以在各個進程中用一個,關掉另外一個沒用的,只留個自己用的socket就行,另一個對方用
import os import socket socket1,socket2=socket.socketpair() pid=os.fork() if pid==0: print('子進程') socket1.close() socket2.send('發給對方父進程'.encode()) else: print('父進程') socket2.close() recv=socket1.recv(1024) print('父進程收到:',recv.decode())
父進程 子進程 父進程收到: 發給對方父進程
3.多進程multiprocessing中的 socket.socketpair 同 os.fork()原理
import socket from multiprocessing import Process socket1,socket2=socket.socketpair() def test(): print(socket1) print(socket2) p1=Process(target=test) p2=Process(target=test) p1.start() p2.start()
<socket.socket fd=4, family=AddressFamily.AF_UNIX, type=SocketKind.SOCK_STREAM, proto=0> <socket.socket fd=5, family=AddressFamily.AF_UNIX, type=SocketKind.SOCK_STREAM, proto=0> <socket.socket fd=4, family=AddressFamily.AF_UNIX, type=SocketKind.SOCK_STREAM, proto=0> <socket.socket fd=5, family=AddressFamily.AF_UNIX, type=SocketKind.SOCK_STREAM, proto=0>
import socket from multiprocessing import Process socket1,socket2=socket.socketpair() def test(): print(socket1) print(socket2) # socket2.close() #可以不close, 但是沒有意義,除非在單個進程里 socket1 和socket2這兩個自己和自己玩 一個發,一個接 print('socket1 send to socket2 hello') socket1.send(b'hello') def test2(): print(socket1) print(socket2) # socket1.close() recv=socket2.recv(1024) print('test2 recv',recv.decode()) p1=Process(target=test) p2=Process(target=test2) p1.start() p2.start()
<socket.socket fd=4, family=AddressFamily.AF_UNIX, type=SocketKind.SOCK_STREAM, proto=0> <socket.socket fd=5, family=AddressFamily.AF_UNIX, type=SocketKind.SOCK_STREAM, proto=0> socket1 send to socket2 hello <socket.socket fd=4, family=AddressFamily.AF_UNIX, type=SocketKind.SOCK_STREAM, proto=0> <socket.socket fd=5, family=AddressFamily.AF_UNIX, type=SocketKind.SOCK_STREAM, proto=0> test2 recv hello
4.多線程Thearding中的 socket.socketpair 同單個進程中的 socket.socketpair原理
1.多線程都是 在一個進程中執行,沒有復制進程的概念,所以 只有一個socketpair 對,所以不能close 任何一個 socket, 如果關了,這個唯一的一對連接可就斷了,就不能收發工作了
2.多進程這種可以close 是因為子進程復制又復制了一對socketpari(),就像創建了快捷方式,刪除一個就好像 刪了快捷方式 ,文件還在,如果文件也刪了就真的關閉了,沒法通信了
import socket from threading import Thread socket1,socket2=socket.socketpair() def test(): print('socket1 send to socket2 hello') socket1.send(b'hello') def test2(): recv=socket2.recv(1024) print('test2 recv',recv.decode()) p1=Thread(target=test) p2=Thread(target=test2) p1.start() p2.start()
socket1 send to socket2 hello test2 recv hello