python學(xué)習(xí)教程之socket庫(kù)的基本使用(網(wǎng)絡(luò)編程-套接字)
一、關(guān)于 socket 的介紹
Socket 又稱 "套接字",應(yīng)用程序通常通過 "套接字" 向網(wǎng)絡(luò)發(fā)出請(qǐng)求或者應(yīng)答網(wǎng)絡(luò)請(qǐng)求,使主機(jī)間或者一臺(tái)計(jì)算機(jī)上的進(jìn)程間可以通訊。python中提供了兩個(gè)基本的 Socket 模塊:服務(wù)端 Socket 和客戶端 Socket,當(dāng)創(chuàng)建了一個(gè)服務(wù)端 Socket 后,這個(gè) Socket 就會(huì)在本機(jī)的一個(gè)端口上等待連接,當(dāng)客戶端 Socket 訪問這個(gè)端口,兩者完成連接后就能夠進(jìn)行交互了。
二、創(chuàng)建套接字對(duì)象(Socket 的實(shí)例化)
在使用 Socket 進(jìn)行編程時(shí),需要先實(shí)例化一個(gè) Scoket 類,Python 中,我們用 socket()函數(shù)來創(chuàng)建套接字。
關(guān)于 socket 函數(shù)的用法:
scoket(family,type[,protocol])
第一個(gè)參數(shù) family 是指定應(yīng)用程序使用的通信協(xié)議的協(xié)議族,有:
Family參數(shù) | 描述 |
socket.AF_UNIX | 只能夠用于單一的Unix系統(tǒng)進(jìn)程間通信 |
socket.AF_INET | 服務(wù)器之間網(wǎng)絡(luò)通信 |
socket.AF_INET6 | IPv6 |
默認(rèn)值為 AF_INET
第二個(gè)參數(shù) type 為要?jiǎng)?chuàng)建套接字的類型
Type參數(shù) | 描述 |
socket.SOCK_STREAM | 流式socket , 當(dāng)使用TCP時(shí)選擇此參數(shù) |
socket.SOCK_DGRAM | 數(shù)據(jù)報(bào)式socket ,當(dāng)使用UDP時(shí)選擇此參數(shù) |
socket.SOCK_RAW | 原始套接字,允許對(duì)底層協(xié)議如IP、ICMP進(jìn)行直接訪問 |
第三個(gè)參數(shù) protocol 是可選項(xiàng),指明所要接收的協(xié)議類型,通常為 0 或者不填。
Type參數(shù) | 描述 |
socket.IPPROTO_RAW | 相當(dāng)于protocol=255,此時(shí)socket只能用來發(fā)送IP包,而不能接收任何的數(shù)據(jù)。發(fā)送的數(shù)據(jù)需要自己填充IP包頭,并且自己計(jì)算校驗(yàn)和。 |
socket.IPPROTO_IP | 相當(dāng)于protocol=0,此時(shí)用于接收任何的IP數(shù)據(jù)包。其中的校驗(yàn)和和協(xié)議分析由程序自己完成。 |
接下來我們實(shí)例化一個(gè)簡(jiǎn)單的 TCP 類型的 Socket
測(cè)試代碼:
import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print(s) print(type(s))
代碼解釋:
- 首先肯定需要使用 import 導(dǎo)入 socket 庫(kù);
- 用一個(gè)自定義參數(shù)(我這里用的 s )來接收創(chuàng)建的套接字對(duì)象;
- 輸出套接字對(duì)象以及它的類型。
運(yùn)行結(jié)果:
關(guān)于運(yùn)行結(jié)果的解釋:
fd=332: 表示套接字的文件描述符(file descriptor),在此處為332。
family=2: 表示套接字的地址族(address family),這里是IPv4地址族(AF_INET)。
type=1: 表示套接字的類型(socket type),這里是流式套接字(SOCK_STREAM),用于TCP協(xié)議。
proto=0: 表示套接字使用的協(xié)議,這里是默認(rèn)協(xié)議(通常與套接字類型相關(guān))。
<class 'socket.socket'>: 表示所創(chuàng)建的對(duì)象屬于Python的socket模塊中的socket類。
三、套接字對(duì)象方法(Socket 常用函數(shù))
首先介紹服務(wù)端函數(shù)
1、bind 函數(shù)
該函數(shù)是服務(wù)端函數(shù),會(huì)將之前創(chuàng)建的套接字與指定的IP地址和端口進(jìn)行綁定,使用點(diǎn)直接調(diào)用該方法,以元組(host, port)的形式表示地址。
比如我們綁定本地的 12345 端口:
s.bind(('127.0.0.1', 12345))
注意這里用到了兩次括號(hào),因?yàn)?bind 方法的參數(shù)需要是一個(gè)包含主機(jī)地址和端口號(hào)的元組。
2、listen 函數(shù)
該函數(shù)也是服務(wù)端函數(shù),用于在使用TCP的服務(wù)端開啟監(jiān)聽模式,只有一個(gè)參數(shù),指定在拒絕連接之前,操作系統(tǒng)可以掛起的最大連接數(shù)量,該值至少為1,大部分應(yīng)用程序設(shè)為 5 即可。
在服務(wù)端開啟監(jiān)聽,設(shè)置操作系統(tǒng)可以掛起的最大連接數(shù)量為 5 :
s.listen(5)
listen() 只是讓套接字處于監(jiān)聽狀態(tài),并沒有接收請(qǐng)求,接收請(qǐng)求需要使用 accept() 函數(shù)。
3、accept 函數(shù)
當(dāng)套接字處于監(jiān)聽狀態(tài)時(shí),可以通過 accept() 函數(shù)來接收客戶端請(qǐng)求,該函數(shù)也是服務(wù)端函數(shù),接受 TCP 連接并返回(conn,address),返回一個(gè)新的套接字來和客戶端通信,其中 conn 是新的套接字對(duì)象,可以用來接收和發(fā)送數(shù)據(jù),address 是連接客戶端的地址。
比如我們就使用 conn 和 address 這兩個(gè)參數(shù)(可自定義)來接收 accept 函數(shù)返回的值
conn, address = s.accept()
下面介紹客戶端函數(shù)
4、connect 與 connect_ex 函數(shù)
connect() 是客戶端程序用來連接服務(wù)端的方法,客戶端連接到 address 處的套接字,一般 address 的格式為元組(host, port),如果連接出錯(cuò),會(huì)返回 socket.error 錯(cuò)誤。
比如我們連接到剛才創(chuàng)建的套接字,即本地的 12345 端口:
import socket c = socket.socket() c.connect(('127.0.0.1', 12345))
只有經(jīng)過 connect 連接成功后的套接字對(duì)象才能調(diào)用發(fā)送和接受方法(send/recv),所以服務(wù)端的 s 對(duì)象不能 send 或者 recv 。
還有一個(gè) connect_ex 函數(shù),功能與 connect 相同,只是成功返回 0,失敗返回 error 的值。
下面是一些常見的公共函數(shù)
5、send 、 sendall 、sendto 函數(shù)
send() :用于發(fā)送 TCP 數(shù)據(jù)
用法:s.send(string[,flag])
將 string 中的數(shù)據(jù)發(fā)送到連接的套接字,返回值是要發(fā)送的字節(jié)數(shù)量,該數(shù)量可能小于 string 的字節(jié)大小。
sendall() :完整發(fā)送TCP數(shù)據(jù)
用法:s.sendall(string[,flag])
與 send() 類似,將 string 中的數(shù)據(jù)發(fā)送到連接的套接字,但在返回之前會(huì)嘗試發(fā)送所有數(shù)據(jù),成功返回None,失敗則拋出異常。
關(guān)于參數(shù)的說明:
string: 這是要發(fā)送的數(shù)據(jù),通常是一個(gè)字符串。這是必需的參數(shù)。
flag : 這是一個(gè)可選的參數(shù),用于指定發(fā)送數(shù)據(jù)的附加選項(xiàng),在大多數(shù)情況下可以省略。
比如我們將 "Hello, server!" 字符串通過UTF-8編碼轉(zhuǎn)換為字節(jié)數(shù)據(jù),然后使用套接字的 send 方法發(fā)送這些字節(jié)數(shù)據(jù)到連接的服務(wù)端:
c.send("Hello, server!".encode('utf-8'))
sendto :用于發(fā)送 UDP 數(shù)據(jù)
用法:s.sendto(string[,flag],address)
將數(shù)據(jù)發(fā)送到套接字,address是形式為(ipaddr,port)的元組,指定遠(yuǎn)程地址,返回值是發(fā)送的字節(jié)數(shù)。
6、recv 與 recvfrom 函數(shù)
recv :接受TCP套接字的數(shù)據(jù),數(shù)據(jù)以字符串形式返回。
用法:s.recv(bufsize[,flag])
參數(shù)說明:
bufsize: 這是一個(gè)整數(shù),表示要接收的最大字節(jié)數(shù)。接收的實(shí)際數(shù)據(jù)可能少于或等于這個(gè)值,取決于發(fā)送端發(fā)送的數(shù)據(jù)量。
flag(可選): 這是一個(gè)可選的參數(shù),用于指定接收數(shù)據(jù)的附加選項(xiàng)。在大多數(shù)情況下,可以省略這個(gè)參數(shù)。
通過 recv 方法接收最多 1024 字節(jié)的數(shù)據(jù),我們將接收到的字節(jié)數(shù)據(jù)解碼為 UTF-8 編碼的字符串,最后打印出來:
re = c.recv(1024) print(re.decode('utf-8'))
recvfrom:接受 UDP 套接字的數(shù)據(jù),與 recv() 類似,但返回值是(data, address)。其中 data 包含接收數(shù)據(jù)的字符串,address 是發(fā)送數(shù)據(jù)的套接字地址。
特別說明:recvfrom 函數(shù)是可以在沒有進(jìn)行 connect 的情況下使用的,對(duì)于 UDP 套接字,可以在未連接的狀態(tài)下使用 recvfrom 來接收數(shù)據(jù)。recvfrom 通常與 UDP 一起使用,因?yàn)?UDP 是一個(gè)無(wú)連接協(xié)議,而 recvfrom 提供了從發(fā)送端獲取地址信息的能力。在 TCP 中,由于是面向連接的,地址信息通常在連接建立時(shí)就已經(jīng)確定了,所以 recv 通常就足夠了。
示例:
import socket # 創(chuàng)建一個(gè)UDP套接字 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 綁定本地地址和端口 s.bind(('127.0.0.1', 12345)) # 接收數(shù)據(jù),設(shè)置bufsize為最大接收字節(jié)數(shù) data, address = s.recvfrom(1024) # 打印接收到的數(shù)據(jù)和發(fā)送端地址信息 print(f"Received data: {data.decode('utf-8')}") print(f"Received from: {address}")
7、close 函數(shù)
該函數(shù)用于關(guān)閉套接字
直接使用點(diǎn)調(diào)用即可
s.close()
三、簡(jiǎn)單的服務(wù)端和客戶端示例
服務(wù)端代碼:
import socket # 創(chuàng)建一個(gè)TCP套接字 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 綁定主機(jī)和端口 server_socket.bind(('127.0.0.1', 12345)) # 監(jiān)聽連接 server_socket.listen() print("Server is listening for incoming connections...") # 接受客戶端連接 client_socket, client_address = server_socket.accept() print(f"Connection established with {client_address}") # 接收數(shù)據(jù) data = client_socket.recv(1024) print(f"Received data: {data.decode('utf-8')}") # 發(fā)送響應(yīng) response = "Hello, client!" client_socket.send(response.encode('utf-8')) # 關(guān)閉連接 client_socket.close() server_socket.close()
客戶端代碼:
import socket # 創(chuàng)建一個(gè)TCP套接字 client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 連接到服務(wù)器 client_socket.connect(('127.0.0.1', 12345)) # 發(fā)送數(shù)據(jù) data_to_send = "Hello, server!" client_socket.send(data_to_send.encode('utf-8')) # 接收響應(yīng) response = client_socket.recv(1024) print(f"Received response: {response.decode('utf-8')}") # 關(guān)閉連接 client_socket.close()
先開啟服務(wù)端,再運(yùn)行客戶端
運(yùn)行效果:
四、關(guān)于 socket 庫(kù)相關(guān)方法函數(shù)的總結(jié)
Socket 創(chuàng)建和配置:
socket(family, type, proto=0, fileno=None):創(chuàng)建一個(gè)套接字對(duì)象。
gethostname():獲取主機(jī)名。
通用套接字方法:bind(address):將套接字綁定到指定的地址。
listen(backlog):開始監(jiān)聽傳入連接請(qǐng)求。
accept():接受連接,返回新的套接字和對(duì)端地址。
connect(address):連接到遠(yuǎn)程套接字。
close():關(guān)閉套接字。
數(shù)據(jù)收發(fā):send(bytes):發(fā)送數(shù)據(jù)。
recv(bufsize):接收數(shù)據(jù)。
UDP 相關(guān)方法:sendto(data, address):發(fā)送UDP數(shù)據(jù)到指定地址。
recvfrom(bufsize):接收UDP數(shù)據(jù)和對(duì)端地址。設(shè)置和獲取套接字選項(xiàng):
setsockopt(level, optname, value):設(shè)置套接字選項(xiàng)。
getsockopt(level, optname, buflen=None):獲取套接字選項(xiàng)。獲取主機(jī)信息:
gethostbyname(hostname):通過主機(jī)名獲取IP地址。
gethostbyaddr(ip_address):通過IP地址獲取主機(jī)名。
總結(jié)
到此這篇關(guān)于python學(xué)習(xí)教程之socket庫(kù)的基本使用的文章就介紹到這了,更多相關(guān)python socket庫(kù)基本使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python分支語(yǔ)句與循環(huán)語(yǔ)句應(yīng)用實(shí)例分析
這篇文章主要介紹了Python分支語(yǔ)句與循環(huán)語(yǔ)句應(yīng)用,結(jié)合具體實(shí)例形式詳細(xì)分析了Python分支語(yǔ)句與循環(huán)語(yǔ)句各種常見應(yīng)用操作技巧與相關(guān)注意事項(xiàng),需要的朋友可以參考下2019-05-05在python中利用GDAL對(duì)tif文件進(jìn)行讀寫的方法
今天小編就為大家分享一篇在python中利用GDAL對(duì)tif文件進(jìn)行讀寫的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-11-11Python辦公自動(dòng)化之發(fā)送電子郵件和Outlook集成
Python辦公?動(dòng)化是利?Python編程語(yǔ)?來創(chuàng)建腳本和程序,以簡(jiǎn)化、加速和?動(dòng)化?常辦公任務(wù)和?作流程的過程,本文主要介紹一下如何利用Python實(shí)現(xiàn)發(fā)送電子郵件和Outlook集成,需要的可以參考下2023-12-12Python中如何使用Pandas庫(kù)自定義函數(shù)
Pandas是Python中用于數(shù)據(jù)分析和處理的強(qiáng)大庫(kù),它提供了豐富的功能,可以輕松地處理各種類型的數(shù)據(jù),在實(shí)際應(yīng)用中,我們經(jīng)常需要對(duì)數(shù)據(jù)進(jìn)行復(fù)雜的轉(zhuǎn)換、計(jì)算或聚合操作,而這些操作往往不能僅靠Pandas內(nèi)置的函數(shù)完成,這時(shí),自定義函數(shù)就顯得尤為重要2025-01-01Python的內(nèi)建模塊itertools的使用解析
這篇文章主要介紹了Python的內(nèi)建模塊itertools的使用解析,itertools是python的迭代器模塊,itertools提供的工具相當(dāng)高效且節(jié)省內(nèi)存,Python的內(nèi)建模塊itertools提供了非常有用的用于操作迭代對(duì)象的函數(shù),需要的朋友可以參考下2023-09-09