目錄
一、socket
二、傳輸協議
三、UDP資料發送
發送資料
接收資料
四、echo服務器
五、聊天程式
一、socket

(該圖片單單只為了學習一個英語單詞)
socket也叫做套接字,是應用層和傳輸層之間的橋梁,利用socket我們可以通過網路完成行程間通信:

應用層封裝好資料給socket,socket會將資料傳遞給傳輸層,經過一層層的傳輸,通過網路傳給另一臺電腦,再經過一層層決議,決議到socket后,socket將資料給應用層,
socket本質是編程介面(API),是對TCP/IP協議的封裝,封裝成的socket更容易使用TCP/IP協議,它是面向客戶-服務器模型設計的,針對客戶和服務器的程式提供了不同的系統呼叫,
服務器可以看做大型的計算機,功能更強,資料大部分都存放在服務器里,可以在自己的電腦或者手機下載一個客戶端,客戶端里面存放的資料量并不大,比如說,手機下載一個愛奇藝的客戶端,想下載視頻,那么需要socket發送一個請求到服務器,服務器接收到信號之后再將資料傳輸給手機,手機才能下載,
socket(套接字)之間的連接可以分為三個步驟:服務器監聽(服務器等待別人連接)、客戶端請求(告訴服務器自己想干什么)、連接確認(雙方確認連接),
接下來創建一個套接字物件:
from socket import *#匯入套接字模塊
s = socket(AF_INET,SOCK_DGRAM)#s是一個socket物件,擁有發送和接收網路資料的能力
函式里有兩個引數必須寫:AF_INET規定使用IPV4協議用于Internet行程間的通信,下一個引數可以是SOCK_STREAM(TCP協議)或者SOCK_DGRAM(UDP協議)
---TCP慢但是穩定不會丟失資料
---UDP快但是可能會丟失資料,被黑客攻擊
二、傳輸協議
UDP——User Datagram Protocol,用戶資料報協議,
是無連接的、簡單的、面向資料報的傳輸層協議,在發送資料時,不會跟對方建立連接,且不確定對方是否能收到,只是簡單的將資料傳輸過去,并不能保證能不能到達目的地,因為UDP傳輸資料時不用建立連接,并且沒有超時重發等機制,所以傳輸資料速度很快,適用于QQ之類的,
TCP——Transmission Control Protocol,傳輸控制協議
是一個面向連接的協議,就是說建立連接時,必須確定建立了一個連接,一個TCP的連接必須經過三次對話,主機A想跟主機B對話,則主機A向主機B發送一個連接請求的資料包,接著主機B向主機A發送一個同意的連接,主機A收到后,向B發送一個資料包,確認主機B的要求,三次對話完成,然后才傳輸正式的資料,TCP占用的資源更多結構更復雜,TCP可以更保證資料的正確性,可以保證資料傳輸的順序,
網路通信時,雙方的協議應該一樣,
三、UDP資料發送
發送資料
sendto函式可以實作資料發送,函式中添加元組,元組里是IP地址和埠號,通過IP地址和埠號找到接收方,(代碼中的IP和埠是從網路除錯助手看到的)
from socket import *
s = socket(AF_INET,SOCK_DGRAM)#IPv4協議,UDP協議
s.sendto("hello",("192.168.0.106",8080))#向IP是192.168.0.106的8080埠發送hello
我們利用網路除錯助手接收資料,協議是UDP,跟發送方相同,埠號默認可用動態埠(8080),可以換成其他可用埠,編程中做相應的修改即可,點擊打開,

程式運行后會報錯:

因為網路之間資料發送要使用位元組流,應使用encode(),就可以將前面的字串轉換為位元組流 :
s.sendto("hello".encode(),("192.168.0.106",8080))
修改后會如下:

通過網路除錯助手可以看到發送方的網路地址和埠號:

因為程式沒有系結埠號,所以每次運行程式發送資料的埠可能會變,
如果發送中文,會發現亂碼,因為python中文默認是UTF-8編碼,而網路除錯助手是GB2312編碼,發送的資料編碼和解碼不一樣,所以會亂碼,所以我們的python指定使用GB2312編碼:
from socket import *
s = socket(AF_INET,SOCK_DGRAM)#IPv4協議,UDP協議
s.sendto("你好".encode("gb2312"),("192.168.0.106",8080))
然后就可以正常的發送資訊:

可以將地址、內容都賦值給變數,進行優化 :
from socket import *
s = socket(AF_INET,SOCK_DGRAM)#IPv4協議,UDP協議
addr = ("192.168.0.106",8080)
date = input("請輸入內容:")
s.sendto(date.encode("gb2312"),addr)
效果如下:

接收資料
如果想使用VS接收資料,則
s.recvfrom(1024)
程式運行到這里時會阻塞,等待接收資料,1024表示本次接收所能接收的最大位元組數,程式接收完后應該:
s.close()
因為物件s是占用一定空間的,當用不到s后,應該及時的關閉,代碼如下:
from socket import *#匯入模塊
addr = ("192.168.0.106",8080)#準備接收方的地址
s = socket(AF_INET,SOCK_DGRAM)
s.sendto("你好鴨".encode("gb2312"),addr)#發送內容,轉換為位元組流
redate = s.recvfrom(1024)
print(redate)
s.close()
運行結果如下:

網路除錯助手接收到資訊后會自動得到對方的地址(如圖中的遠程主機),所以網路除錯助手發送資料時知道往哪里發送,
收到的資料是一個元組,第一個元素是內容,開頭是“b”,表示是一個位元組流,想得到收到的訊息,應該:
print(redate[0].decode())#0是第一個元素,decode轉換為字串
又因為網路除錯助手是GB2312編碼,所以應該指定為GB2312解碼:
print(redate[0].decode("gb2312"))
效果如下:

ps:如果是字串常量,在字串前加”b”,效果跟加encode一樣
s.sendto(b"hhhh",addr)
內容可以是 ASCII范圍內的字符和其它十六進制形式的字符資料,但不能是中文等非ASCII字符,
前面是網路埠先接受資料,這樣網路埠發送資料時才能知道往哪里發,如果是網路埠直接發送,則編程時應該先系結一個IP地址和埠號:
s.bind(("",8888))
IP會自動是本機IP,所以沒必要指定,但發現網路除錯助手不能主動跟別人發送資料,所以還是應該主動給網路除錯助手發送一個資料,此時,得到發送資料的埠就是8888,
四、echo服務器
echo服務器是非常有用的用于除錯和檢測的工具,協議的作用也很簡單,就是接收到什么原樣發回,
新建一個python檔案寫入:
from socket import *#匯入模塊
udpSock = socket(AF_INET,SOCK_DGRAM)
udpSock.bind(("",8888))#系結一個埠
while True:#使其不停的做收發
recvData = udpSock.recvfrom(1024)#首先接收發送來的資料
udpSock.sendto(recvData[0],recvData[1])#將資料發送回去
udpSock.close()
原程式為:
from socket import *#匯入模塊
s = socket(AF_INET,SOCK_DGRAM)
s.bind(("",7777))
addr = ("113.54.204.147",8888)
s.sendto("hello,你好".encode(),addr)
redata = s.recvfrom(1024)
print(redata[0].decode())
都運行之后會發現發送什么,就會返還什么,程式的作用就是可以測驗網路通不通,
五、聊天程式
一個檔案寫入:
from socket import *#匯入模塊
udpSock = socket(AF_INET,SOCK_DGRAM)
udpSock.bind(("",8888))#系結一個埠
addr = ("113.54.204.147",7777)
while True:
recvData = udpSock.recvfrom(1024)
print(recvData[0].decode())
data = input("想說啥:")
udpSock.sendto(data.encode(),addr)
udpSock.close()
另一個寫入:
from socket import *#匯入模塊
s = socket(AF_INET,SOCK_DGRAM)
s.bind(("",7777))
addr = ("113.54.204.147",8888)
while True:
data = input(":")
s.sendto(data.encode(),addr)
recvData = s.recvfrom(1024)
print(recvData[0].decode())
s.close()
因為都是python撰寫,用的是utf-8,所以不用再指定,
此時是一個半雙工程式,就是說收發訊息不能同時進行,因為執行接收時會阻塞,不能發送訊息,
其實可以通過并發編程來實作,但是在多行程中不能使用input(),
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/298330.html
標籤:其他
