一文帶你瞭解Python Socket 程式設計
阿新 • • 發佈:2022-03-15
大家好,我是皮皮。
前言
Socket又稱為套接字,它是所有網路通訊的基礎。網路通訊其實就是程序間的通訊,Socket主要是使用IP地址,協議,埠號來標識一個程序。埠號的範圍為0~65535(使用者埠號一般大於1024),協議有很多種,一般我們經常用到的就是TCP,IP,UDP。下面我們來詳細瞭解下Socket吧。
一、匯入Socket模組
因為要操作套接字,所以需要用到套接字模組,系統中自帶的就很不錯,下面我們來匯入:
import socket
二、Socket基本用法
1.建立一個簡單的Socket連線
#建立Tcp/Ip套接字 s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #流式Socket #建立Udp/Ip套接字 s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #資料報式Socket socket.AF_UNIX #只能夠用於單一的Unix系統程序間通訊 socket.AF_INET6 #只能夠用於IPv6通訊 socket.SOCK_RAW #原始套接字,可以處理ICMP、ARP等網路報文,其它的不行 socket.SOCK_SEQPACKET #可靠的連續資料包服務
2.協議對應埠
應用程式 FTP TFTP TELNET SMTP DNS HTTP SSH MYSQL POP3 MONGO
埠 21,20 69 23 25 53 80 22 3306 110 27017
協議 TCP UDP TCP TCP UDP TCP TCP TCP TCP TCP
3.Socket函式
#建立Socket連線,比Connect更高階,可以自動解析不是數字的host地址,相容IPv4和 IPv6 socket.create_connection(address=('localhost',4320),timeout=4,source_address=('localhost',4320)) #前後兩個埠號一定要是一致,不然會報錯 #構建一對已連線的套接字物件,新建立的套接字都是不可繼承的 socket.socketpair(family=socket.AF_INET,type=socket.SOCK_STREAM,proto=0) #從檔案描述符獲取到socket連線物件 socket.fromfd(fd=ab.fileno(),family=socket.AF_INET,type=socket.SOCK_STREAM,proto=0) #套接字物件的型別 socket.SocketType #返回套接字的5元組列表地址 ,支援IPV4/IPV6解析 socket.getaddrinfo(host='localhost',port=3453,family=socket.AF_INET,type=socket.SOCK_STREAM,proto=socket.IPPROTO_TCP,flags=0) output: [(<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_STREAM: 1>, 6, '', ('127.0.0.1', 3453))] #獲取主機名 socket.gethostname() socket.getfqdn() socket.getfqdn(socket.gethostname()) #將主機名轉化為IP地址 socket.gethostbyname('www.baidu.com') #不支援IPV6解析 socket.gethostbyname_ex('www.baidu.com') #返回三元組,(主機名,相同地址的其它可用主機名的列表,IPv4 地址列表) #網路ip地址 socket.gethostbyname(socket.getfqdn(socket.gethostname())) #將ip地址轉化為主機名,返回三元組(主機名,相同地址的其它可用主機名的列表,IPv4地址列表),支援IPV4/IPV6 socket.gethostbyaddr('192.168.1.4') #解析主機名或者IP地址 socket.getnameinfo(('192.168.1.4',5434),0) #判斷是否支援IPV6 socket.has_ipv6 #返回服務所使用的埠號 socket.getservbyname('https','tcp') #第一個引數為服務協議:Https,Http;第二個為傳輸協議:Tcp Udp #返回埠所對應的服務 socket.getservbyport(443,'tcp') #設定主機名(僅限於Unix) socket.sethostname(name) #返回網絡卡資訊的列表(僅限於Unix) socket.if_nameindex() #32位位元組儲存Ip地址(序列化) socket.inet_aton('127.0.0.1') #將32位位元組轉化為Ip地址(反序列化) socket.inet_ntoa(b'\x7f\x00\x00\x01')
4.套接字函式
1).伺服器端函式
s.bind((host,port)) #將地址繫結到套接字,以(host,port)的元祖形式
s.listen(num) #建立最多num個連線,最好別太大
s.accept() #等待並接受客戶端的連線,返回新的套接字物件和(host,port)元祖
2).客戶端函式
s.connect((host,port)) #建立與伺服器的連線,以(host,port)的元祖形式
s.connect_ex((host,port)) #和上面的功能差不多,只是出錯了不拋異常,只是返回出錯碼
3).通用函式
s.recv(size,flag) #接收最多size個大小的資料,flag可以忽略,返回值為資料是字串形式 s.send(str,flag) #傳送str資料,返回值是要傳送的位元組數量,可能資料未全部發送 s.sendall(str,flag) #傳送全部str資料,成功返回None,失敗則丟擲異常 s.recv(size,flag) #接受最多size個數據,並以字串形式返回 s.recvfrom(str,flag) #與recv相同,但是返回值是(接收資料的字串,傳送資料的套接字地址)的元祖形式 s.sendto(str,flag,address) #連線到當前套接字的遠端地址。返回值是傳送的位元組數,主要用於UDP s.getpeername() #返回連線套接字的遠端地址。返回值通常是元組(host,port) s.getsockname() #返回套接字自己的地址。通常是一個元組(host,port) s.setsockopt(level,optname,value) # 設定給定套接字選項的值。 #假如埠被socket使用過,並且利用socket.close()來關閉連線,但此時埠還沒有釋放,要經過TIME_WAIT的過程之後才能使用;為了實現埠的馬上覆用,可以選擇setsocket()函式來達到目的。 #level:選項定義的層次。支援SOL_SOCKET、IPPROTO_TCP、IPPROTO_IP和IPPROTO_IPV6。 #optname:需設定的選項。SO_REUSEADDR SO_REUSEPORT #value:設定選項的值。 s.getsockopt(level,optname,buflen) #返回套接字選項的值。buflen:快取長度 s.settimeout(time) #設定socket連線超時時間,單位為秒,超時一般在剛建立套接字時設定 s.gettimeout() #返回當前超時的時間,單位是秒,如果沒有設定超時,則返回None。 s.close() #關閉套接字 s.fileno() #套接字的檔案描述符 s.shutdown(how) # 關閉連線一邊或兩邊 s.setblocking(bool) #是否阻塞(預設True),如果設定False,那麼accept和recv時一旦無資料,則報錯。 s.makefile() #建立一個與該套接字相關聯的檔案
5.一個簡單的客戶端與服務端互動
Server.py
import socket
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 建立socket物件
s.bind(('127.0.0.1',4323)) # 繫結地址
s.listen(5) # 建立5個監聽
while True:
conn,addr= s.accept() # 等待客戶端連線
print('歡迎{}'.format(addr)) #列印訪問的使用者資訊
while True:
data=conn.recv(1024)
dt=data.decode('utf-8') #接收一個1024位元組的資料
print('收到:',dt)
aa=input('伺服器發出:')
if aa=='quit':
conn.close() #關閉來自客戶端的連線
s.close() #關閉伺服器端連線
else:
conn.send(aa.encode('utf-8'))
Client.py
import socket
import sys
c=socket.socket() # 建立socket物件
c.connect(('127.0.0.1',4323)) #建立連線
while True:
ab=input('客戶端發出:')
if ab=='quit':
c.close() #關閉客戶端連線
sys.exit(0)
else:
c.send(ab.encode('utf-8')) #傳送資料
data=c.recv(1024) #接收一個1024位元組的資料
print('收到:',data.decode('utf-8'))
可以看到我們實現了一個全雙工的Tcp/Ip聊天工具,對於伺服器和客戶端來說,均可收發檔案。
三、總結
Python中的socket程式設計難度不大,不過你要想寫好的Socket也不容易,希望本文能讓大家受益匪淺,畢竟小編可是把絕大多數經常用到的Api的功能都展示了。
小夥伴們,快快用實踐一下吧!如果在學習過程中,有遇到任何問題,歡迎加我好友,我拉你進Python學習交流群共同探討學習。