python環境下的TCP網絡編程
網絡概念
網絡是由節點和連線構成,表示諸多對象及其相互聯繫。在數學上,網絡是一種圖,一般認爲專指加權圖。網絡除了數學定義外,還有具體的物理含義,即網絡是從某種相同類型的實際問題中抽象出來的模型。在計算機領域中,網絡是信息傳輸、接收、共享的虛擬平臺,通過它把各個點、面、體的信息聯繫到一起,從而實現這些資源的共享。
客戶端/服務端
1.在計算機中,客戶端和服務端的架構模式,區分爲硬件模式和軟件模式
- 硬件客戶端
客戶端(Client)或稱爲用戶端,是指與服務器相對應,爲客戶提供本地服務的程序。除了一些只在本地運行的應用程序之外,一般安裝在普通的客戶機上,需要與服務端互相配合運行。因特網發展以後,較常用的用戶端包括瞭如萬維網使用的網頁瀏覽器,收寄電子郵件時的電子郵件客戶端,以及即時通訊的客戶端軟件等。對於這一類應用程序,需要網絡中有相應的服務器和服務程序來提供相應的服務,如數據庫服務,電子郵件服務等等,這樣在客戶機和服務器端,需要建立特定的通信連接,來保證應用程序的正常運行。 - 服務端
服務端是爲客戶端服務的,服務的內容諸如向客戶端提供資源,保存客戶端數據。 - 軟件客戶端/服務端
軟件服務器和硬件服務器不同的是:軟件服務器是安裝在硬件上的一種特殊的軟件,可以通 過程序的執行完成數據檢索、數據處理、數據存取等等各種特性,再通過網絡進行數據的共享通信,完成提供網絡數據服務的功能!
IP&PORT
- IP: internet protocal 網絡互聯協議,中文縮寫:網協;英文縮寫:IP
- PORT:端口 在通過 IP 地址確定了網絡上的某個具體主機之後,具體的數據通信主要是通過工作在計算 機中的軟件執行的。
- 計算機中的端口號的範圍是 0~65535 之間
端口號根據其使用場景,一般區分爲公用端口、動態端口、保留端口
公用端口:0~1023
動態端口:1024~65535
保留端口:一般是 unix 系統中超級用戶進程分配保留端口號
協議
協議:英文名稱 protocal,是多方協商計議之後得出的約定、規則、規範 (ps:不是強制約定的)
通常情況下爲了讓工作在網絡中的多臺計算機之間能友好的完成不同軟件的數據的通信,出現了互聯網數據傳輸協議的概念,通過協議的約束,不同地域環境的計算機可以通過網絡完 成流暢的正確的數據交互。
計算機網絡數據傳輸協議目前最主流的就是歐洲計算機制造協會聯盟,也稱爲國際標準化組 織 ISO 指定的 OSI/RM 七層網絡傳輸模型。
協議族
協議:通常指代單獨的一個協議,協議族通常指代互相關聯的一組協議,協議棧指代某一組互 相關聯的協議和他們所屬的 OSI 模型的層級結構。
- 常見的網絡傳輸協議
協議名稱 | 協議描述 |
---|---|
HTTP | 超文本傳輸協議 |
HTTPS | 提供安全通道的超文本傳輸協議 |
FTP | 文件傳輸協議 |
TELNET | 虛擬終端協議 |
SSH | 安全外殼協議 |
POP3 | 郵局協議 ( 版本 3) |
IP | 數據包 交換 協議 |
TCP | 端對端傳輸協議 |
UDP | 數據廣播協議 |
DNS | 域名解析 協議,可以通過 nslookup查看域名解析信息 |
DHCP | 動態主機配置協議 |
PYTHON 傳輸層網絡編程
socket由來
python2.x/python3.x 對於網絡編程的支持都是非常友好的,本身支持兩部分非常有用 的網絡編程方式。
⚫ 傳統網絡編程
⚫ 非阻塞異步網絡編程
底層通過套接字 socket 對象的連接,完成多種協議的網絡程序服務端/客戶端的開發和數據通信。
socket 最初是爲同一主機上的應用程序創建,是的主機上運行的一個程序與另一個程序之 間可以完成數據通信操作,程序也稱爲進程,就出現了不同進程間進行數據交互的操作,因 爲交互的模式不同,所以也一般將程序中的套接字區分爲兩種
⚫ 面向文件的套接字:通過文件進行數據交互
⚫ 面向網絡的套接字:通過網絡進行數據交互
python中的套接字
套接字模型對象,爲了能明確的表示網絡中一臺數據交互的主機,需要通過 IP 地址尋址確 定主機位置,通過 PORT 端口號確定主機交互接口
在網絡套接字交互過程中,出現了兩種類型的套接字模型
⚫ 面向連接的套接字模型
⚫ 面向無連接的套接字模型
面向連接的套接字模型,在進行網絡數據傳輸過程中,首先要創建一個連接模型,通過指定 的連接模型進行數據的交互,類似我們生活中撥打電話一樣,首先保證通話連接的基礎上才 能完成通話內容的交互,比較經典的如 TCP 端對端傳輸協議就是面向連接的套接字對象
面向無連接的套接字模型,在進行網絡數據傳輸過程中,不需要有效的網絡連接模型,在數據傳輸過程中只負責發送/接受,不保證數據的完整性和實效性;類似我們生活中的廣播電臺、電視信號等等,操作效率要比面向連接的套接字模型更加高效;比較經典的 UDP 廣播 協議使用的就是面向無連接的套接字對象
python 中提供的網絡連接套接字,主要包含在 socket 模塊中 socket 模塊提供了 socket()函數可以完成如上描述的各種網絡套接字的構建、通信等操作
⚫ 基本語法結構 socket.socket(socket_family, socket_type, protocal=0) socket_family:socket 地址家族,AF_UNIX/AF_LOCAL 或者 AF_INET socket_type:socket 連接類型 面向連接的(SOCK_STREAM),面向無連接的(SOCK_DGRAME) protocal:傳輸協議,一般不用設置,使用默認值進行自動匹配就好
⚫ 創建 TCP 協議的套接字 socket 對象
tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
⚫ 創建 UDP 協議的套接字 socket 對象
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
ocket 套接字常用操作
屬性 | 描述 |
---|---|
s.bind() | 綁定(主機名稱、端口)到一個套接字上 |
s.listen() | 設置並啓動 TCP 監聽 |
s.accept() | 等待客戶端連接 |
s.connect() | 連接指定服務器 |
s.connect_ex() | 連接指定服務器,如果出現錯誤返回錯誤信息 |
s.recv() | 接受 TCP 消息 |
s.recv_into( | 接受 TCP 消息到緩衝區 |
s.send() | 發送 TCP 消息 |
s.sendall() | 完整發送 TCP 消息 |
s.recvfrom() | 接受 UDP 消息 |
s.recvfrom_into() | 接受 UDP 消息到緩衝區 |
s.sendto() | 發送 UDP 消息 |
s.shutdown() | 關閉連接對 |
s.close() | 關閉套接字對 |
TCP編程
TCP:Transmission Control Protocal 傳輸控制協議 是一種面向連接的,可靠的、基於字節流的傳輸層通信協議
數據傳輸的可靠性的處理方式,經典的 TCP 模型中通過如下兩種方式完成連接的可靠性
⚫ 三次握手建立連接 ◼
A- > B:發送一個尋址請求碼 seq=100;
B->A:返回一個應答 ack=101 ◼
A->B:發送一個確認請求碼 seq=101,確認連接;
B->A:返回一個應答 ack=300 ◼
A->B:發送一個連接請求碼 ack=300;
B->A:返回應答 ack=80 ◼
A 和 B 之間開始進行數據交互
⚫ 四次揮手斷開連接 ◼
A->B:發送一個數據驗證請求碼 seq=100,
B->A:返回一個應答 ack=101 ◼
A->B:發送一個傳輸結束標記:seq=101;
B->A:返回一個應答 ack=200 ◼
A->B:發送一個確認結束標記:seq=200;
B->A:返回一個應答 ack=300 ◼
A->B:發送連接斷開標記:seq=300;
B->A:返回斷開連接應答:ack=400
正是有了三次握手和四次揮手對於連接可靠性的保障,才讓 TCP 協議端對端的數據交互變 得可行,但是同樣由於該協議的過於可靠,被有心人利用經常實施 DDOS 拒絕服務攻擊!
python環境下的TCP服務端開發
"""
tcp服務端開發
version 1.1.0
author lkk
email [email protected]
"""
import socket
# 定義服務端主機信息
HOST = ''
PORT = 8888
ADDRESS = (HOST, PORT)
BUFFER = 1024
# 創建可以操作tcp協議的socket對象
test_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 將socket對象與服務端主機信息進行綁定
test_tcp.bind(ADDRESS)
# 開始監聽
print('開始啓動服務端')
test_tcp.listen(255)
# 等待客服端的連接
while True:
print('等待客戶端連接>>>>')
client_socket, client_addr = test_tcp.accept()
print('客戶端:{}連接成功'.format(client_addr))
client_socket.send("歡迎您的使用".encode('gbk'))
while True:
info = client_socket.recv(BUFFER)
msg1 = input('服務端:')
client_socket.send(msg1.encode('gbk'))
try:
print('客戶端:{}'.format(info.decode('gbk')))
except:
print('客戶端:{}'.format(info.decode('gbk')))
if msg1 == b'bye':
print("客戶端:{}退出成功".format(client_addr))
client_socket.close()
break
# 關閉【服務端一般情況下不要求關閉】
tcp_socket.close()
python環境下的TCP客戶端開發
"""
tcp客戶端開發
version 1.1.0
author lkk
email [email protected]
"""
import socket
HOST = '192.168.11.203'
PORT = 8888
ADDRESS = (HOST, PORT)
BUFFER = 1024
test_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
test_client.connect(ADDRESS)
while True:
info = test_client.recv(BUFFER)
print("服務端:", info.decode("gbk"))
msg1 = input('客戶端:')
test_client.send(msg1.encode('gbk'))
# print('客戶端:{}'.format())
if msg1 == 'bye':
test_client.close()
break