Python Socket 編程知識(shí)點(diǎn)詳細(xì)介紹
前言:
Socket又稱為套接字,它是所有網(wǎng)絡(luò)通信的基礎(chǔ)。網(wǎng)絡(luò)通信其實(shí)就是進(jìn)程間的通信,Socket主要是使用IP地址,協(xié)議,端口號(hào)來標(biāo)識(shí)一個(gè)進(jìn)程。端口號(hào)的范圍為0~65535(用戶端口號(hào)一般大于1024),協(xié)議有很多種,一般我們經(jīng)常用到的就是TCP,IP,UDP。下面我們來詳細(xì)了解下Socket吧。
一、導(dǎo)入Socket模塊
因?yàn)橐僮魈捉幼?,所以需要用到套接字模塊,系統(tǒng)中自帶的就很不錯(cuò),下面我們來導(dǎo)入:
import socket
二、Socket基本用法
1.建立一個(gè)簡(jiǎn)單的Socket連接
#創(chuàng)建Tcp/Ip套接字 s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #流式Socket #創(chuàng)建Udp/Ip套接字 s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #數(shù)據(jù)報(bào)式Socket socket.AF_UNIX ?#只能夠用于單一的Unix系統(tǒng)進(jìn)程間通信 socket.AF_INET6 ?#只能夠用于IPv6通信 socket.SOCK_RAW ?#原始套接字,可以處理ICMP、ARP等網(wǎng)絡(luò)報(bào)文,其它的不行 socket.SOCK_SEQPACKET ?#可靠的連續(xù)數(shù)據(jù)包服務(wù)
2.協(xié)議對(duì)應(yīng)端口
應(yīng)用程序 FTP TFTP TELNET SMTP DNS HTTP SSH MYSQL POP3 MONGO
端口 21,20 69 23 25 53 80 22 3306 110 27017
協(xié)議 TCP UDP TCP TCP UDP TCP TCP TCP TCP TCP
3.Socket函數(shù)
#創(chuàng)建Socket連接,比Connect更高級(jí),可以自動(dòng)解析不是數(shù)字的host地址,兼容IPv4和 IPv6
socket.create_connection(address=('localhost',4320),timeout=4,source_address=('localhost',4320)) ?#前后兩個(gè)端口號(hào)一定要是一致,不然會(huì)報(bào)錯(cuò)
#構(gòu)建一對(duì)已連接的套接字對(duì)象,新創(chuàng)建的套接字都是不可繼承的
socket.socketpair(family=socket.AF_INET,type=socket.SOCK_STREAM,proto=0)
#從文件描述符獲取到socket連接對(duì)象
socket.fromfd(fd=ab.fileno(),family=socket.AF_INET,type=socket.SOCK_STREAM,proto=0)
#套接字對(duì)象的類型
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))]
#獲取主機(jī)名
socket.gethostname()
socket.getfqdn()
socket.getfqdn(socket.gethostname())
#將主機(jī)名轉(zhuǎn)化為IP地址
socket.gethostbyname('www.baidu.com') #不支持IPV6解析
socket.gethostbyname_ex('www.baidu.com') #返回三元組,(主機(jī)名,相同地址的其它可用主機(jī)名的列表,IPv4 地址列表)
#網(wǎng)絡(luò)ip地址
socket.gethostbyname(socket.getfqdn(socket.gethostname()))
#將ip地址轉(zhuǎn)化為主機(jī)名,返回三元組(主機(jī)名,相同地址的其它可用主機(jī)名的列表,IPv4地址列表),支持IPV4/IPV6
socket.gethostbyaddr('192.168.1.4')
#解析主機(jī)名或者IP地址
socket.getnameinfo(('192.168.1.4',5434),0)
#判斷是否支持IPV6
socket.has_ipv6
#返回服務(wù)所使用的端口號(hào)
socket.getservbyname('https','tcp') #第一個(gè)參數(shù)為服務(wù)協(xié)議:Https,Http;第二個(gè)為傳輸協(xié)議:Tcp Udp
#返回端口所對(duì)應(yīng)的服務(wù)
socket.getservbyport(443,'tcp')
#設(shè)置主機(jī)名(僅限于Unix)
socket.sethostname(name)
#返回網(wǎng)卡信息的列表(僅限于Unix)
socket.if_nameindex()
#32位字節(jié)存儲(chǔ)Ip地址(序列化)
socket.inet_aton('127.0.0.1')
#將32位字節(jié)轉(zhuǎn)化為Ip地址(反序列化)
socket.inet_ntoa(b'\x7f\x00\x00\x01')
4.套接字函數(shù)
1).服務(wù)器端函數(shù)
s.bind((host,port)) #將地址綁定到套接字,以(host,port)的元祖形式 s.listen(num) ?#建立最多num個(gè)連接,最好別太大 s.accept() ? ? #等待并接受客戶端的連接,返回新的套接字對(duì)象和(host,port)元祖
2).客戶端函數(shù)
s.connect((host,port)) #建立與服務(wù)器的連接,以(host,port)的元祖形式 s.connect_ex((host,port)) #和上面的功能差不多,只是出錯(cuò)了不拋異常,只是返回出錯(cuò)碼
3).通用函數(shù)
s.recv(size,flag) ? ? ? #接收最多size個(gè)大小的數(shù)據(jù),flag可以忽略,返回值為數(shù)據(jù)是字符串形式 s.send(str,flag) ? ? ? ?#發(fā)送str數(shù)據(jù),返回值是要發(fā)送的字節(jié)數(shù)量,可能數(shù)據(jù)未全部發(fā)送 s.sendall(str,flag) ? ? #發(fā)送全部str數(shù)據(jù),成功返回None,失敗則拋出異常 s.recv(size,flag) ? ? ? #接受最多size個(gè)數(shù)據(jù),并以字符串形式返回 s.recvfrom(str,flag) ? ?#與recv相同,但是返回值是(接收數(shù)據(jù)的字符串,發(fā)送數(shù)據(jù)的套接字地址)的元祖形式 s.sendto(str,flag,address) #連接到當(dāng)前套接字的遠(yuǎn)程地址。返回值是發(fā)送的字節(jié)數(shù),主要用于UDP s.getpeername() ? ? #返回連接套接字的遠(yuǎn)程地址。返回值通常是元組(host,port) s.getsockname() ? ? #返回套接字自己的地址。通常是一個(gè)元組(host,port) s.setsockopt(level,optname,value) # 設(shè)置給定套接字選項(xiàng)的值。 #假如端口被socket使用過,并且利用socket.close()來關(guān)閉連接,但此時(shí)端口還沒有釋放,要經(jīng)過TIME_WAIT的過程之后才能使用;為了實(shí)現(xiàn)端口的馬上復(fù)用,可以選擇setsocket()函數(shù)來達(dá)到目的。 #level:選項(xiàng)定義的層次。支持SOL_SOCKET、IPPROTO_TCP、IPPROTO_IP和IPPROTO_IPV6。 #optname:需設(shè)置的選項(xiàng)。SO_REUSEADDR SO_REUSEPORT #value:設(shè)置選項(xiàng)的值。 s.getsockopt(level,optname,buflen) #返回套接字選項(xiàng)的值。buflen:緩存長(zhǎng)度 s.settimeout(time) ?#設(shè)置socket連接超時(shí)時(shí)間,單位為秒,超時(shí)一般在剛創(chuàng)建套接字時(shí)設(shè)置 s.gettimeout() ? ? ?#返回當(dāng)前超時(shí)的時(shí)間,單位是秒,如果沒有設(shè)置超時(shí),則返回None。 s.close() ? ? ? ? ? #關(guān)閉套接字 s.fileno() ? ? ? ? ?#套接字的文件描述符 s.shutdown(how) ? ? # 關(guān)閉連接一邊或兩邊 s.setblocking(bool) #是否阻塞(默認(rèn)True),如果設(shè)置False,那么accept和recv時(shí)一旦無數(shù)據(jù),則報(bào)錯(cuò)。 s.makefile() ? ? ? ?#創(chuàng)建一個(gè)與該套接字相關(guān)聯(lián)的文件
5.一個(gè)簡(jiǎn)單的客戶端與服務(wù)端交互
Server.py
import socket?
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM) ? ? ? ? ? ? # 創(chuàng)建socket對(duì)象
s.bind(('127.0.0.1',4323)) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?# 綁定地址
s.listen(5) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # 建立5個(gè)監(jiān)聽
while True:
? ? conn,addr= s.accept() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # 等待客戶端連接
? ? print('歡迎{}'.format(addr)) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#打印訪問的用戶信息
? ? while True:
? ? ? ? data=conn.recv(1024)?
? ? ? ? dt=data.decode('utf-8') ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #接收一個(gè)1024字節(jié)的數(shù)據(jù)?
? ? ? ? print('收到:',dt)
? ? ? ? aa=input('服務(wù)器發(fā)出:')?
? ? ? ? if aa=='quit':
? ? ? ? ? ? conn.close() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#關(guān)閉來自客戶端的連接
? ? ? ? ? ? s.close() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #關(guān)閉服務(wù)器端連接
? ? ? ? else:
? ? ? ? ? ? conn.send(aa.encode('utf-8')) ? ? ? ? ? ? ? ? ? ? ? #發(fā)送數(shù)據(jù)Client.py
import socket ??
import sys
c=socket.socket() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # 創(chuàng)建socket對(duì)象
c.connect(('127.0.0.1',4323)) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#建立連接
while True:
? ? ab=input('客戶端發(fā)出:')
? ? if ab=='quit':
? ? ? ? c.close() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #關(guān)閉客戶端連接
? ? ? ? sys.exit(0)
? ? else:
? ? ? ? c.send(ab.encode('utf-8')) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #發(fā)送數(shù)據(jù)
? ? ? ? data=c.recv(1024) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#接收一個(gè)1024字節(jié)的數(shù)據(jù)
? ? ? ? print('收到:',data.decode('utf-8')) ? ? ? ? ? ? ? ? ? ?#輸出接收的信息
可以看到我們實(shí)現(xiàn)了一個(gè)全雙工的Tcp/Ip聊天工具,對(duì)于服務(wù)器和客戶端來說,均可收發(fā)文件。
三、總結(jié)
Python中的socket編程難度不大,不過你要想寫好的Socket也不容易,希望本文能讓大家受益匪淺,畢竟小編可是把絕大多數(shù)經(jīng)常用到的Api的功能都展示了。
到此這篇關(guān)于Python Socket 編程知識(shí)點(diǎn)詳細(xì)介紹的文章就介紹到這了,更多相關(guān)Python Socket 編程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Github?Copilot結(jié)合python的使用方法詳解
最近也是聽說github出了一種最新的插件叫做copilot,于是申請(qǐng)了,下面這篇文章主要給大家介紹了關(guān)于Github?Copilot結(jié)合python使用的相關(guān)資料,需要的朋友可以參考下2022-04-04
使用Django實(shí)現(xiàn)把兩個(gè)模型類的數(shù)據(jù)聚合在一起
這篇文章主要介紹了使用Django實(shí)現(xiàn)把兩個(gè)模型類的數(shù)據(jù)聚合在一起,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-03-03
pandas分組排序 如何獲取第二大的數(shù)據(jù)
這篇文章主要介紹了pandas分組排序 獲取第二大的數(shù)據(jù)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-03-03
Python爬蟲使用Selenium+PhantomJS抓取Ajax和動(dòng)態(tài)HTML內(nèi)容
這篇文章主要介紹了Python爬蟲使用Selenium+PhantomJS抓取Ajax和動(dòng)態(tài)HTML內(nèi)容,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02
如何利用Python和OpenCV對(duì)圖像進(jìn)行加水印詳解
Python使用opencv是因?yàn)橛X得它足夠強(qiáng)大,很多圖像處理這塊都是用的它,最近就用opencv添加個(gè)水印,這篇文章主要給大家介紹了關(guān)于如何利用Python和OpenCV對(duì)圖像進(jìn)行加水印的相關(guān)資料,需要的朋友可以參考下2021-10-10
Python使用pandas模塊實(shí)現(xiàn)表之間的關(guān)聯(lián)
在數(shù)據(jù)分析和處理中,表之間的關(guān)聯(lián)是非常常見的操作,本文為大家介紹了pandas中實(shí)現(xiàn)表之間的關(guān)聯(lián)有四種方式,感興趣的小伙伴可以了解一下2023-07-07

