摘要:中卻發(fā)生了異常。接收數(shù)據(jù)使用函數(shù)接收數(shù)據(jù)在中返回的是對象,在中返回的是。注意函數(shù)返回的數(shù)據(jù)長度是小于或者等于參數(shù)指定的長度的,要接收到指定長度的數(shù)據(jù),需要循環(huán)接收數(shù)據(jù)。當(dāng)一個(gè)被回收時(shí)會自動(dòng)關(guān)閉,但是不要依賴這種機(jī)制,不需要時(shí)就主動(dòng)的。
本文介紹使用Python進(jìn)行Socket網(wǎng)絡(luò)編程,假設(shè)讀者已經(jīng)具備了基本的網(wǎng)絡(luò)編程知識和Python的基本語法知識,本文中的代碼如果沒有說明則都是運(yùn)行在Python 3.4下。
Python的socket功能封裝在socket庫中,要使用socket,記得先import socket,socket庫的詳細(xì)介紹參見官方文檔。
首先創(chuàng)建一個(gè)socket,使用socket庫中得socket函數(shù)創(chuàng)建。
Pythonimport socket # create an INET, STREAM socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
例子中創(chuàng)建了一個(gè)TCP socket,socket.socket函數(shù)的前兩個(gè)參數(shù)的默認(rèn)值是socket.AF_INET和socket.SOCK_STREAM,創(chuàng)建TCP socket時(shí)可以直接寫成socket.socket()。
連接服務(wù)器使用socket的connect函數(shù)連接到服務(wù)器,以下幾種參數(shù)都是合法的。
Pythons.connect(("localhost", 8000)) s.connect(("127.0.0.1", 8000)) s.connect(("www.baidu.com", 80))發(fā)送數(shù)據(jù)
發(fā)送數(shù)據(jù)有兩個(gè)方法send和sendall,send不能保證所有的數(shù)據(jù)都發(fā)送完了,它會返回已發(fā)送數(shù)據(jù)的長度,程序要循環(huán)發(fā)送數(shù)據(jù)直到所有數(shù)據(jù)都已發(fā)送完畢。
Pythondef mysend(s, msg): total_len = len(msg) total_sent = 0 while total_sent < total_len: sent = s.send(msg[total_sent:]) if sent == 0: raise RuntimeError("socket connection broken") total_sent += sent
sendall能夠保證所有的數(shù)據(jù)都已發(fā)送完畢,除非發(fā)送過程中出現(xiàn)了錯(cuò)誤,它實(shí)際上也是循環(huán)發(fā)送數(shù)據(jù)直到所有數(shù)據(jù)發(fā)送完成。
這里還要講一個(gè)需要特別注意的地方,從一個(gè)例子開始吧:
Pythonimport socket s = socket.socket() s.connect(("www.baidu.com", 80)) s.sendall("test")
都是上面講過的東西,沒什么特別的,分別在Python 2和Python 3中執(zhí)行以上的代碼,結(jié)果是:
Python# Python 2.7 >>> import socket >>> s = socket.socket() >>> s.connect(("www.baidu.com", 80)) >>> s.sendall("test")
Python 2中執(zhí)行成功。
Python# Python 3.4 >>> import socket >>> s = socket.socket() >>> s.connect(("www.baidu.com", 80)) >>> s.sendall("test") Traceback (most recent call last): File "", line 1, in TypeError: "str" does not support the buffer interface
Python 3中卻發(fā)生了異常。
同樣的代碼換個(gè)環(huán)境卻不能執(zhí)行了,我沒有寫錯(cuò)呀,怒砸電腦。好吧,你確實(shí)沒寫錯(cuò),是環(huán)境變了,導(dǎo)致這個(gè)結(jié)果的變化請移步官方的說明。
接收數(shù)據(jù)使用recv函數(shù)接收數(shù)據(jù):
Pythondata = s.recv(4096)
在Python 3中返回的是bytes對象,在Python 2中返回的是string。注意函數(shù)返回的數(shù)據(jù)長度是小于或者等于參數(shù)指定的長度的,要接收到指定長度的數(shù)據(jù),需要循環(huán)接收數(shù)據(jù)。
Pythondef myreceive(s, msglen): chunks = [] bytes_recd = 0 while bytes_recd < msglen: chunk = s.recv(min(msglen - bytes_recd, 2048)) if chunk == b"": raise RuntimeError("socket connection broken") chunks.append(chunk) bytes_recd = bytes_recd + len(chunk) return b"".join(chunks)關(guān)閉連接
當(dāng)連接不再需要時(shí)可以使用close關(guān)閉socket連接,關(guān)閉后的連接不能再進(jìn)行任何操作。當(dāng)一個(gè)socket被回收時(shí)會自動(dòng)關(guān)閉,但是不要依賴這種機(jī)制,不需要socket時(shí)就主動(dòng)的close。
服務(wù)端服務(wù)端程序執(zhí)行的步驟:
1. 創(chuàng)建服務(wù)端socket
1. 將服務(wù)端socket綁定到指定的地址和端口
1. 監(jiān)聽連接
1. 接受客戶端連接
1. 處理客戶端的數(shù)據(jù)
1. 關(guān)閉客戶端連接
一個(gè)簡單的echo server示例:
Pythonimport socket HOST = "" PORT = 10022 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((HOST, PORT)) s.listen(10) conn, addr = s.accept() while True: data = conn.recv(1024) if not data: break conn.sendall(data) conn.close()
客戶端程序:
Pythonimport socket HOST = "localhost" PORT = 10022 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) s.sendall(b"hello socket") data = s.recv(1024) print("Received", repr(data)) s.close()錯(cuò)誤處理
socket處理過程中發(fā)生錯(cuò)誤會拋出異常,socket相關(guān)的異常有:
- socket.error
- socket.herror
- socket.gaierror
- socket.timeout
Pythonimport socket HOST = None PORT = 10022 try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((HOST, PORT)) s.listen(10) except: socket.error as msg: print(msg)參考資料
Socket Programming HOWTO
Porting Python 2 Code to Python 3
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/37491.html
摘要: Abstract Sockets are used nearly everywhere, but are one of the most severely misunderstood technologies around. This is a 10,000 foot overview of sockets. It’s not really a tutorial - you’ll s...
摘要:同時(shí)無論在哪種平臺上,都可以用進(jìn)行系統(tǒng)編程。這樣導(dǎo)入模塊并使用生成隨機(jī)數(shù)中的模塊提供了生成隨機(jī)數(shù)的函數(shù)。生成的隨機(jī)數(shù)介于和之間??梢詮淖约憾x的范圍中生成一個(gè)隨機(jī)數(shù),如下所示操作日期和時(shí)間你可以從日期中提取所需的值,如下所示。 翻譯:瘋狂的技術(shù)宅https://likegeeks.com/python-... 本文首發(fā)微信公眾號:前端先鋒歡迎關(guān)注,每天都給你推送新鮮的前端技術(shù)文章 ...
摘要:本文原發(fā)于個(gè)人博客在英文中的含義為連接兩個(gè)物品的凹槽,像,意為眼窩,此外還有插座的意思。協(xié)議,所是用的傳輸協(xié)議,目前有三種。,也稱為無連接的,使用協(xié)議。當(dāng)函數(shù)返回時(shí),意味著對端已經(jīng)關(guān)閉。 本文原發(fā)于個(gè)人博客 Socket 在英文中的含義為(連接兩個(gè)物品的)凹槽,像the eye socket,意為眼窩,此外還有插座的意思。在計(jì)算機(jī)科學(xué)中,socket 通常是指一個(gè)連接的兩個(gè)端點(diǎn),這里的...
摘要:當(dāng)一個(gè)客戶端連接時(shí),它將返回一個(gè)新的對象,對象中有表示當(dāng)前連接的和一個(gè)由主機(jī)端口號組成的連接的元組,更多關(guān)于元組值的內(nèi)容可以查看地址族一節(jié)中的詳情這里必須要明白我們通過調(diào)用方法擁有了一個(gè)新的對象。 博客原文: https://keelii.com/2018/09/24/socket-programming-in-python/ 說明 本書翻譯自 realpython 網(wǎng)站上的文章教程 ...
閱讀 1819·2019-08-30 13:54
閱讀 2734·2019-08-29 17:27
閱讀 1123·2019-08-29 17:23
閱讀 3357·2019-08-29 15:20
閱讀 1234·2019-08-29 11:28
閱讀 1576·2019-08-26 10:39
閱讀 1324·2019-08-26 10:29
閱讀 649·2019-08-26 10:13