C/S B/S 架構python
C:client端,客戶端 B:Browser,瀏覽器 S:server,服務端 C/S 客戶端與服務器之間的架構:QQ,微信,遊戲,APP等都屬於C/S架構 優勢:安全性高,個性化設置,功能全面,響應速度快。 缺點:開發成本高,維護成本高。(基於APP),面向的客戶固定 B/S:瀏覽器與服務器之間的架構:它屬於C/S架構,最近幾年比較流行的特殊的C/S架構 優勢:開發維護成本低,面向用戶普遍 缺點:安全性相對低,響應速度相對慢,個性化的設置單一
互聯網通訊的原理shell
osi 七層協議(tcp/ip五層協議或tcp/ip四層協議)編程
七層:應用層,表示層,會話層,傳輸層,網絡層,數據鏈路層,物理層瀏覽器
五層:應用層(應,表,會),傳輸層,網絡層,數據鏈路層,物理層安全
四層:應用層(應,表,會),傳輸層,網絡層,網絡接口層(數,物)服務器
每層運行常見的物理設備:微信
傳輸層:四層交換機,四層的路由器網絡
網絡層:路由器,三層交換機架構
數據鏈路層:網橋,以太網交換機,網卡socket
物理層:中繼器,集線器,雙絞線
下面咱們來倒着分析一下五層協議
物理層
一系列的物理鏈接介質:網線,光纖,電纜,無線網絡等
發送的數據是0101011100形式的比特數據流,主要是基於電器特性發送高低電壓(電信號),高電壓對應數字1,低電壓對應數字0
數據鏈路層:遵循以太網協議
數據鏈路層的由來:單純的電信號0和1沒有任何意義,必須規定電信號多少位一組,每組表明什麼意思
數據鏈路層的功能:定義了電信號的分組方式
以太網協議(ethernet):統一了電信號的分組方式
Ethernet規定:
Ethernet規定:一組電信號構成一個數據報,叫作「幀」 每一數據幀分紅:報頭 head 和數據 data 兩部分 head 包含:(固定18個字節) 發送者/源地址,6個字節 接收者/目標地址,6個字節 數據類型,6個字節 data 包含:(最短46個字節,最長1500字節) 數據包的具體內容 head 長度 + data 長度 = 最短64字節,最長1518個字節,超過最大限制就分片發送 MAC地址:head 中包含的源地址和目標地址的由來,ethernet 規定接入 internet 的設備都必須具有網卡,發送端和接收端的地址即是指網卡地址,即MAC地址 MAC地址:每塊網卡出廠時都被燒製上一個世界惟一的MAC地址,長度爲48位2進制,一般由12位16進制數表示(前六位是廠商編號,後六位是流水線號) 廣播: 計算機最原始的通訊方式就是吼. 數據的分組(源地址目標地址) + 廣播: 理論上個人計算機就能夠通訊了.可是效率過低,每臺計算機都須要接收廣播的消息,查看是不是給本身的數據.比廣播風暴還要嚴重. 因此: 廣播它是有範圍的,在同一子網,局域網內是經過廣播的方式,發消息.
網絡層:遵循IP協議
網絡層由來:是爲了肯定目標計算機在局域網內的位置
網絡層功能:引入一套新的地址用來區分不一樣的廣播域/子網,這套地址即網絡地址
IP協議:規定網絡地址的協議叫 IP 協議,它定義的地址稱之爲 ip 地址,普遍採用的v4版本即ipv4,它規定網絡地址由32位2進製表示
一個ip地址一般寫爲四段十進制數,如:172.16.10.1
ip地址範圍:0.0.0.0 - 255.255.255.255
ip地址分紅兩個部分:
網絡部分:標識子網
主機部分:標識主機
注意:單純的ip地址段只是標識了ip地址的種類,從網絡部分或主機部分都沒法辨識一個ip所處的子網
例:172.16.10.1與172.16.10.2並不能肯定兩者處於同一子網
子網掩碼:
所謂」子網掩碼」,就是表示子網絡特徵的一個參數。它在形式上等同於IP地址,也是一個32位二進制數字,它的網絡部分所有爲1,主機部分所有爲0。好比,IP地址172.16.10.1,若是已知網絡部分是前24位,主機部分是後8位,那麼子網絡掩碼就是11111111.11111111.11111111.00000000,寫成十進制就是255.255.255.0。 知道」子網掩碼」,咱們就能判斷,任意兩個IP地址是否處在同一個子網絡。方法是將兩個IP地址與子網掩碼分別進行AND運算(兩個數位都爲1,運算結果爲1,不然爲0),而後比較結果是否相同,若是是的話,就代表它們在同一個子網絡中,不然就不是。 好比,已知IP地址172.16.10.1和172.16.10.2的子網掩碼都是255.255.255.0,請問它們是否在同一個子網絡?二者與子網掩碼分別進行AND運算, 172.16.10.1:10101100.00010000.00001010.000000001 255255.255.255.0:11111111.11111111.11111111.00000000 AND運算得網絡地址結果:10101100.00010000.00001010.000000001->172.16.10.0 172.16.10.2:10101100.00010000.00001010.000000010 255255.255.255.0:11111111.11111111.11111111.00000000 AND運算得網絡地址結果:10101100.00010000.00001010.000000001->172.16.10.0 結果都是172.16.10.0,所以它們在同一個子網絡。 總結一下,IP協議的做用主要有兩個,一個是爲每一臺計算機分配IP地址,另外一個是肯定哪些地址在同一個子網絡。
ip數據包
ip數據包也分爲head和data部分,無須爲ip包定義單獨的欄位,直接放入以太網包的data部分
head:長度爲20到60字節
data:最長爲65,515字節。
而以太網數據包的」數據」部分,最長只有1500字節。所以,若是IP數據包超過了1500字節,它就須要分割成幾個以太網數據包,分開發送了。
傳輸層:遵循端口協議(tcp/udp協議)
傳輸層的由來:網絡層的IP地址幫咱們區分子網,以太網的MAC幫咱們找到主機, 而後你們使用的都是應用程序,你的電腦上可能同時開啓QQ,微信等多個應用程序那麼咱們經過ip和Mac找到了目標計算機,如何標識這臺主機上的應用程序,答案就是端口,端口即應用程序與網卡關聯的編號
傳輸層功能:創建端口到端口的通訊
端口: 0~65535端口號.
1~1023系統佔用的端口號.
1024~8000以內:通常都是有軟件佔用.
自定義端口: 8000 之後
tcp協議:
可靠傳輸,TCP數據包沒有長度限制,理論上能夠無限長,可是爲了保證網絡的效率,一般TCP數據包的長度不會超過IP數據包的長度,以確保單個TCP數據包沒必要再分割。
以太網頭|ip頭|tcp頭|數據
udp協議:
不可靠傳輸,」報頭」部分一共只有8個字節,總長度不超過65,535字節,正好放進一個IP數據包。
以太網頭|ip頭|udp頭|數據
TCP的三次握手四次揮手
三次握手:
第一次: 客戶端向服務器發送創建聯繫的syn請求和seq序號
第二次: 服務器向客戶端回覆ack確認號和創建聯繫的syn請求和seq序號
第三次: 客戶端向服務器回覆ack確認號
四次揮手:
第一次: 客戶端向服務器發送斷開聯繫的fin請求和seq序號
第二次: 服務器向客戶端回覆ack確認號
第三次: 服務器向客戶端發送斷開聯繫的fin請求和seq序號
第四次: 客戶端向服務器回覆ack確認號
udp與tcp的區別
一、TCP的優缺點 (1)TCP的優勢: TCP的優勢是:可靠、穩定。它體如今TCP在傳遞數據以前,會有三次握手來創建鏈接;在數據傳遞時,採用校驗和、序列號、確認應答、超時重發、流量控制、擁塞控制,爲了提升性能,還採用了滑動窗口、延遲應答和捎帶應答等機制;在數據傳完後,會斷開鏈接以節約系統資源。 (2)TCP的缺點: TCP的缺點:運行速度慢,效率低,佔用系統資源多,易被攻擊。由於TCP在傳遞數據以前,要先創建鏈接,這會消耗時間;在數據傳遞時,確認機制、重傳機制、擁塞控制機制等都會消耗大量的時間,並且要在每臺設備上維護全部的傳輸鏈接,每一個鏈接都會佔用系統的CPU、內存等資源;TCP有確認機制、三次握手機制,這致使TCP容易受到DOS、DDOS、CC等攻擊。收到STN洪水攻擊,是由於使用 TCP的時候服務器端須要listen,這時須要設置backlog。 二、UDP的優缺點 (1)UDP的優勢:運行速度較快,比TCP安全。 1)運行速度快,由於 UDP鏈接沒有TCP的三次握手、確認應答、超時重發、流量控制、擁塞控制等機制,並且UDP是一個無狀態的傳輸協議,因此它在傳遞數據時很是快。 2)較安全,由於沒有TCP的那些機制,UDP較TCP被攻擊者利用的漏洞就會少一些。但UDP也是沒法避免攻擊的,好比:UDP Flood攻擊等。 (2)UDP的缺點:不可靠,不穩定。 由於UDP沒有TCP那些可靠的機制,在數據傳遞時,若是網絡質量很差,就會很容易丟包。 三、TCP和UDP的特色 (1)TCP的特色 TCP協議是一種有鏈接、可靠的、面向字節流、相對比較慢、點對點的傳輸層協議。TCP協議適用於對可靠性要求比較高的場合。 (2)UDP的特色 UDP協議是一種無鏈接,不可靠、面向數據報、速度比較快、可實現一對一,多對一的傳輸層協議。UDP協議適用於對實時性有要求的場合。由於UDP不保證可靠性,因此UDP也沒有重傳機制,也沒有擁塞機制,它只是盡最大努力交付數據。
使用TCP的應用:Web瀏覽器;文件傳輸程序。
使用UDP的應用:域名系統 (DNS);視頻流;IP語音(VoIP),微信qq。
應用層:遵循應用軟件本身定義的協議
應用層由來: 用戶使用的都是應用程序,均工做於應用層,互聯網是開放的,你們均可以開發本身的應用程序,數據多種多樣,必須規定好數據的組織形式
應用層功能:規定應用程序的數據格式。
socket套接字.
五層協議: 從傳輸層包括傳輸層如下,都是操做系統幫助咱們封裝的各類head.你不用去關心.應用層與傳輸層之間存在一個socket套接字
# socket的套接字 ''' socket 套接字,它存在於傳輸層與應用層之間的抽象層, 1. 避免你學習各層的接口,以及協議的使用, socket已經封裝好了全部的接口. 直接使用這些接口或者方法便可,使用起來方便,提高開發效率. 2. socket就是一個模塊.經過使用學習模塊提供的功能, 創建客戶端與服務端的通訊,使用方便. '''
單個客戶與服務端通訊.
服務端:
import socket # phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 1. 建立socket對象 phone = socket.socket() # 能夠不寫,默認TCP協議下的連接模式 # 2. 綁定ip地址和端口 phone.bind(('127.0.0.1', 8848)) # '127.0.0.1'本地迴環地址 # 3. 監聽 phone.listen(5) # 4. 接收鏈接 conn, addr = phone.accept() # 程序夯住,等待客戶端的數據 from_client_data = conn.recv(1024) # 至多接收1024個字節 print(f'來自客戶端{addr}消息{from_client_data.decode("utf-8")}') to_client = input('>>>') conn.send(to_client.encode('utf-8')) conn.close() phone.close()
客戶端:
import socket # 1. 建立socket對象 phone = socket.socket() # 能夠默認不寫 # 鏈接服務器ip地址與端口 phone.connect(('127.0.0.1', 8848)) # 發消息 to_server = input('>>>').strip() phone.send(to_server.encode('utf-8')) # 接收消息 from_server_data = phone.recv(1024) # 夯住,等待服務端的數據傳過來 print(f'來自服務端消息:{from_server_data.decode("utf-8")}') # 關機 phone.close()
通訊循環.
服務端:
import socket phone = socket.socket() # 能夠默認不寫 phone.bind(('127.0.0.1', 8848)) # 本地迴環地址 phone.listen(5) conn, addr = phone.accept() # 程序夯住 while 1: from_client_data = conn.recv(1024) # 至多接收1024個字節 print(f'來自客戶端{addr}消息{from_client_data.decode("utf-8")}') to_client = input('>>>') conn.send(to_client.encode('utf-8')) conn.close() phone.close() # 不管你的客戶端是否正常關閉,服務端都應該正常關閉,而不是報錯. # 改進版 import socket phone = socket.socket() # 能夠默認不寫 phone.bind(('127.0.0.1', 8888)) # 本地迴環地址 phone.listen(5) conn, addr = phone.accept() # 程序夯住 while 1: try: from_client_data = conn.recv(1024) # 至多接收1024個字節 if from_client_data == b'q': # 接受到客戶端發來的q 退出循環 break print(f'來自客戶端{addr}消息{from_client_data.decode("utf-8")}') to_client = input('>>>') conn.send(to_client.encode('utf-8')) except ConnectionResetError: break conn.close() phone.close()
客戶端:
import socket phone = socket.socket() # 能夠默認不寫 phone.connect(('127.0.0.1', 8888)) while 1: to_server = input('>>>').strip() if to_server.upper() == 'Q': # 若是用戶輸入的是Q/q phone.send('q'.encode('utf-8')) # 向服務端發送 q break # 退出循環 phone.send(to_server.encode('utf-8')) from_server_data = phone.recv(1024) # 夯住,等待服務端的數據傳過來 print(f'來自服務端消息:{from_server_data.decode("utf-8")}') phone.close()
通訊,鏈接循環.
服務端:
import socket phone = socket.socket() phone.bind(('127.0.0.1', 8888)) phone.listen(5) while 1: conn, addr = phone.accept() # 程序夯住 while 1: try: from_client_data = conn.recv(1024) # 至多接收1024個字節 if from_client_data == b'q': break print(f'來自客戶端{addr}消息{from_client_data.decode("utf-8")}') to_client = input('>>>') conn.send(to_client.encode('utf-8')) except ConnectionResetError: break conn.close() phone.close()
客戶端:
import socket phone = socket.socket() # 能夠默認不寫 phone.connect(('127.0.0.1', 8888)) while 1: to_server = input('>>>').strip() if to_server.upper() == 'Q': phone.send('q'.encode('utf-8')) break phone.send(to_server.encode('utf-8')) from_server_data = phone.recv(1024) # 夯住,等待服務端的數據傳過來 print(f'來自服務端消息:{from_server_data.decode("utf-8")}') phone.close()
利用socket完成獲取遠端命令的示例.
服務端
import socket import subprocess phone = socket.socket() phone.bind(('127.0.0.1', 8888)) phone.listen(5) conn, addr = phone.accept() while 1: try: cmd = conn.recv(1024) # dir obj = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,) result = obj.stdout.read() + obj.stderr.read() conn.send(result) except ConnectionResetError: break conn.close() phone.close()
客戶端
import socket phone = socket.socket() phone.connect(('127.0.0.1', 8888)) while 1: cmd = input('>>>').strip() phone.send(cmd.encode('utf-8')) result = phone.recv(1024) # 夯住,等待服務端的數據傳過來 print(result.decode('gbk')) phone.close()