目錄
Socket概念
Python Socket編程
發(fā)送接收緩沖? 消息格式定義
Socket概念
?Socket套接字,一種獨立于協(xié)議的網(wǎng)絡(luò)編程接口,就是對網(wǎng)絡(luò)中不同主機上的應(yīng)用進程之間進行雙向通信的端點。
TCP把連接作為最基本的對象,每一條TCP連接都有兩個端點,這種端點我們叫作套接字(socket)。
IP層的ip地址可以唯一標示主機,而TCP層協(xié)議和端口號可以唯一標示主機的一個進程,這樣我們可以利用ip地址+協(xié)議+端口號唯一標示網(wǎng)絡(luò)中的一個進程。 能夠唯一標示網(wǎng)絡(luò)中的進程后,它們就可以利用socket進行通信了
?
、
Python Socket編程
使用python內(nèi)置的socket庫,目前socket編程,最多是通過tcp協(xié)議進行網(wǎng)絡(luò)通訊的。
tcp進行通訊的程序雙方,分為服務(wù)端和客戶端。
tcp協(xié)議進行通訊的雙方,是需要先建立一個虛擬連接的,然后雙方程序員才能發(fā)送業(yè)務(wù)數(shù)據(jù)信息。
服務(wù)端需要四個步驟:
??????? 1.新建socket
????????2.綁定IP和端口號
??????? 3.監(jiān)聽連接
??????? 4.收發(fā)消息
客戶端需要三個步驟:
??????? 1.新建socket
??????? 2.連接服務(wù)器端
??????? 3.發(fā)收消息
服務(wù)端比客戶端先運行,服務(wù)端先運行然后等待客戶端連接
#TCP 服務(wù)端端程序 server.py
#導(dǎo)入socket庫
from socket import *
#主機地址為0.0.0.0,表示綁定本機所有網(wǎng)絡(luò)接口ip地址
#等待客戶端來連接
IP='127.0.0.1'
#端口號
PORT=50000
#定義一次從socket緩沖區(qū)最多讀入512個字節(jié)數(shù)據(jù)
BUFLEN=512
#實例化一個socket對象
#參數(shù) AF_INET 表示該socket網(wǎng)絡(luò)層使用IP協(xié)議
#參數(shù) SOCK_STREAM 表示該socket傳輸層使用tcp協(xié)議
listenSocket=socket(AF_INET,SOCK_STREAM)
#socket綁定地址和端口
listenSocket.bind((IP,PORT))
#使socket處于監(jiān)聽狀態(tài),等待客戶端的連接請求
#調(diào)用了.listen,就把socket置于等待連接狀態(tài)
#參數(shù)5表示 最多接受多少個等待連接的客戶端
listenSocket.listen(5)
print(f'服務(wù)端啟動成功,在{PORT}端口等待客戶端連接...')
#接收客戶端連接,無客戶端連接時,就處于睡眠狀態(tài)
dataSocket,addr=listenSocket.accept()
print('接受一個客戶端連接:',addr)
while True:
#嘗試讀取對方發(fā)送的消息
#BUFLEN 指定從接收緩沖里最多讀取多少字節(jié)
recved=dataSocket.recv(BUFLEN)
#如果返回空bytes,表示對方關(guān)閉了連接
#退出循環(huán),結(jié)束消息收發(fā)
if not recved:
break
#讀取的學(xué)節(jié)數(shù)據(jù)是bytes類型,需要解碼為字符串
info=recved.decode()
print(f'收到對方信息:{info}')
#發(fā)送的數(shù)據(jù)類型必須是bytes,所以要編碼
dataSocket.send(f'服務(wù)端接收到了信息{info}'.encode())
#服務(wù)端也調(diào)用close()關(guān)閉socket
dataSocket.close()
listenSocket.close()
#TCP 客戶端程序 client.py
from socket import *
IP='127.0.0.1'
SERVER_PORT=50000
BUFLEN=512
#實例化一個socket對象,指明協(xié)議
dataSocket =socket(AF_INET,SOCK_STREAM)
#連接服務(wù)端socket
dataSocket.connect((IP,SERVER_PORT))
while True:
#從終端讀入用戶輸入的字符串
toSend =input('>>>')
# 退出,跳出循環(huán)
if toSend =='exit':
break
#發(fā)送消息,也要編碼為 bytes
dataSocket.send(toSend.encode())
#等待接收服務(wù)段的消息,如果沒有消息就一直等待
recved=dataSocket.recv(BUFLEN)
#如果返回空bytes,表示對方關(guān)閉了連接
if not recved:
break
#打印讀取的信息
print(recved.decode())
dataSocket.close()
運行代碼之前,先查看的有沒有處于50000的端口,然后執(zhí)行server.py再查看端口,然后執(zhí)行client.py再查看端口。
?建立連接后,就能收發(fā)信息了
發(fā)送接收緩沖? 消息格式定義
編程的時候,如果要跟某個IP建立連接,我們需要調(diào)用操作系統(tǒng)提供的?
socket API
。socket?在操作系統(tǒng)層面,可以理解為一個文件。我們可以對這個文件進行一些方法操作。
- 用
listen
方法,可以讓程序作為服務(wù)器監(jiān)聽其他客戶端的連接。- 用
connect
,可以作為客戶端連接服務(wù)器。- 用
send
或write
可以發(fā)送數(shù)據(jù),recv
或read
可以接收數(shù)據(jù)。在建立好連接之后,如果我們想給遠端服務(wù)發(fā)點什么東西,那就只需要對這個文件執(zhí)行寫操作就行了。
剩下的發(fā)送工作自然就是由操作系統(tǒng)內(nèi)核來完成了。
既然是寫給操作系統(tǒng),那操作系統(tǒng)就需要提供一個地方給用戶寫。同理,接收消息也是一樣。這個地方就是?socket 緩沖區(qū)。
- 用戶發(fā)送消息的時候?qū)懡o send buffer(發(fā)送緩沖區(qū))
- 用戶接收消息的時候?qū)懡o recv buffer(接收緩沖區(qū))
也就是說一個socket ,會帶有兩個緩沖區(qū),一個用于發(fā)送,一個用于接收。因為這是個先進先出的結(jié)構(gòu),有時候也叫它們發(fā)送、接收隊列。
?在企業(yè)中開發(fā)的程序通信,消息往往有格式定義。消息的格式定義可以歸入OSI中的表示層
比如:定義的消息,包括消息頭和消息體。
消息頭存放消息的數(shù)據(jù)格式(消息的長度、類型、狀態(tài)等),消息體存放具體傳送的數(shù)據(jù)。
對于TCP協(xié)議傳輸信息的程序來說,格式一定要有明確規(guī)定的消息邊界。因為TCP傳輸?shù)氖亲止?jié)流(bytes stream),如果消息中沒有指定邊界或者長度,接收方就不知道完整的消息從字節(jié)流的哪里開始,到哪里結(jié)束。
指定消息的邊界有兩種方式:
??????? 1.用特殊字節(jié)作為消息的結(jié)尾符號
?????????? 可以用消息中不易出現(xiàn)的字符串(比如 FFFFFF)作為消息的結(jié)尾字符
??????? 2.在消息開頭某個位置,直接指定消息的長度
??????????? UDP協(xié)議通常不用指定邊界,因為UDP是數(shù)據(jù)報協(xié)議,應(yīng)用程序從socket接收到的文章來源:http://www.zghlxwxcb.cn/news/detail-466610.html
??????????? 必定是發(fā)送方發(fā)送的完整消息。{:.notice-info}文章來源地址http://www.zghlxwxcb.cn/news/detail-466610.html
到了這里,關(guān)于Python Socket網(wǎng)絡(luò)編程的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!