客戶端與服務器端架構,這種架構也是從用戶層面(也能夠是物理層面)來劃分的。python
這裏的客戶端通常泛指客戶端應用程序EXE,程序須要先安裝後,才能運行在用戶的電腦上,對用戶的電腦操做系統環境依賴較大。編程
C: Client (客戶端)設計模式
S: Server (服務端)瀏覽器
優勢:緩存
缺點:安全
瀏覽器端與服務器端架構,這種架構是從用戶層面來劃分的。服務器
Browser瀏覽器,其實也是一種Client客戶端,只是這個客戶端不須要你們去安裝什麼應用程序,只需在瀏覽器上經過HTTP請求服務器端相關的資源(網頁資源),客戶端Browser瀏覽器就能進行增刪改查。網絡
B: Browser ( 瀏覽器端 )架構
S: Server (服務端)併發
優勢:
缺點:
總結:
CS架構響應速度快,安全性強,通常應用於局域網中,可是開發維護成本高;BS能夠實現跨平臺,客戶端零維護,可是個性化能力低,響應速度較慢。
問題:數據放在服務端和客戶端的利與弊?
對電信號來作分組。之前每一個公司都有本身的分組方式,後來造成了統一的標準,即以太網協議ethernet。
ethernet規定:一組電信號構成一個數據報,叫作'幀',每一數據幀分紅:報頭head和數據data兩部分
- | - |
---|---|
head | data |
head中包含的源和目標地址由來:ethernet規定接入internet的設備都必須具有網卡,發送端和接收端的地址即是指網卡的地址,即mac地址。
mac地址:每塊網卡出廠時都被燒製上一個世界惟一的mac地址,長度爲48位2進制,一般由12位16進制數表示(前六位是廠商編號,後六位是流水線號)
主機之間「一對全部」的通信模式,網絡對其中每一臺主機發出的信號都進行無條件複製並轉發,全部主機均可以接收到全部信息(無論你是否須要),因爲其不用路徑選擇,因此其網絡成本能夠很低廉。有線電視網就是典型的廣播型網絡,咱們的電視機其實是接受到全部頻道的信號,但只將一個頻道的信號還原成畫面。在數據網絡中也容許廣播的存在,但其被限制在二層交換機的局域網範圍內,禁止廣播數據穿過路由器,防止廣播數據影響大面積的主機。
地址解析協議,即ARP(Address Resolution Protocol),是根據IP地址獲取物理地址的一個TCP/IP協議。
主機發送信息時將包含目標IP地址的ARP請求廣播到網絡上的全部主機,並接收返回消息,以此肯定目標的物理地址。
路由器(Router),是鏈接因特網中各局域網、廣域網的設備,它會根據信道的狀況自動選擇和設定路由,以最佳路徑,按先後順序發送信號。 路由器是互聯網絡的樞紐,"交通警察"。目前路由器已經普遍應用於各行各業,各類不一樣檔次的產品已成爲實現各類骨幹網內部鏈接、骨幹網間互聯和骨幹網與互聯網互聯互通業務的主力軍。路由和交換機之間的主要區別就是交換機發生在OSI參考模型第二層(數據鏈路層),而路由發生在第三層,即網絡層。這一區別決定了路由和交換機在移動信息的過程當中需使用不一樣的控制信息,因此說二者實現各自功能的方式是不一樣的。
路由器(Router)又稱網關設備(Gateway)是用於鏈接多個邏輯上分開的網絡,所謂邏輯網絡是表明一個單獨的網絡或者一個子網。當數據從一個子網傳輸到另外一個子網時,可經過路由器的路由功能來完成。所以,路由器具備判斷網絡地址和選擇IP路徑的功能,它能在多網絡互聯環境中,創建靈活的鏈接,可用徹底不一樣的數據分組和介質訪問方法鏈接各類子網,路由器只接受源站或其餘路由器的信息,屬網絡層的一種互聯設備。
局域網(Local Area Network,LAN)是指在某一區域內由多臺計算機互聯成的計算機組。通常是方圓幾公里之內。局域網能夠實現文件管理、應用軟件共享、打印機共享、工做組內的日程安排、電子郵件和傳真通訊服務等功能。局域網是封閉型的,能夠由辦公室內的兩臺計算機組成,也能夠由一個公司內的上千臺計算機組成。
所謂」子網掩碼」,就是表示子網絡特徵的一個參數。它在形式上等同於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地址的主機能夠提供許多服務,好比Web服務、FTP服務、SMTP服務等,這些服務徹底能夠經過1個IP地址來實現。那麼,主機是怎樣區分不一樣的網絡服務呢?顯然不能只靠IP地址,由於IP地址與網絡服務的關係是一對多的關係。其實是經過「IP地址+端口號」來區分不一樣的服務的。
人們按照分工不一樣把互聯網協議從邏輯上劃分了層級:(通常做爲開發人員,掌握應傳網數物 五層便可):
每層運行常見物理設備:
每層運行常見的協議:
構成
網絡通訊的數據傳輸介質,由鏈接不一樣結點的電纜與設備共同構成。
功能:
基於電器特性發送高低電壓(電信號),高電壓對應數字1,低電壓對應數字0。
由來
單純的電信號0和1沒有任何意義,必須規定電信號多少位一組,每組什麼意思。
功能
基於以太網協議,定義了電信號的分組方式。
功能
引入一套新的地址用來區分不一樣的廣播域/子網,這套地址即網絡地址
由來
有了ethernet、Mac地址、廣播的發送方式,世界上的計算機就能夠彼此通訊了,問題是世界範圍的互聯網是由 一個個彼此隔離的小的局域網組成的,那麼若是全部的通訊都採用以太網的廣播方式,那麼一臺機器發送的包全世界都會收到。
用於標識惟一的一臺計算機(局域網)的地址。
3.3.2 arp協議
由來
通訊是基於Mac的廣播方式實現,計算機在發包時,獲取自身的Mac是容易的,如何獲取目標主機的Mac,就須要經過arp協議
功能
廣播的方式發送數據包, 全部主機接收後拆開包,發現目標IP爲本身的,就響應,返回本身的Mac。
功能
創建端口到端口的通訊
由來
網絡層的IP幫咱們區分子網,以太網層的Mac幫咱們找到主機,而後你們使用的都是應用程序,你的電腦上可能同時開啓qq,暴風影音,等多個應用程序。
那麼咱們經過IP和Mac找到了一臺特定的主機,如何標識這臺主機上的應用程序,答案就是端口,端口即應用程序與網卡關聯的編號。
有了Mac地址+IP地址+端口,咱們就能肯定世界上獨一無二的一臺計算機上的應用程序。
可靠傳輸,TCP數據包沒有長度限制,理論上能夠無限長,可是爲了保證網絡的效率,一般TCP數據包的長度不會超過IP數據包的長度,以確保單個TCP數據包沒必要再分割。
- | - | - | - |
---|---|---|---|
以太網頭 | IP頭 | TCP頭 | 數據 |
不可靠傳輸,」報頭」部分一共只有8個字節,總長度不超過65,535字節,正好放進一個IP數據包。
- | - | - | - |
---|---|---|---|
以太網頭 | IP頭 | UDP頭 | 數據 |
功能
規定應用程序的數據格式。
由來
用戶使用的都是應用程序,均工做於應用層,互聯網是開發的,你們均可以開發本身的應用程序,數據多種多樣,必須規定好數據的組織形式 。
TCP協議:
提供面向鏈接的服務,在傳送數據以前必須先創建鏈接,數據傳送完成後要釋放鏈接。所以TCP是一種可靠的的運輸服務,可是正由於這樣,不可避免的增長了許多的開銷,好比確認,流量控制等。對應的應用層的協議主要有 SMTP,TELNET,HTTP,FTP 等。
UDP協議:
在傳送數據前不須要先創建鏈接,遠地的主機在收到UDP報文後也不須要給出任何確認。雖然UDP不提供可靠交付,可是正是由於這樣,省去和不少的開銷,使得它的速度比較快,好比一些對實時性要求較高的服務,就經常使用的是UDP。對應的應用層的協議主要有 DNS,TFTP,DHCP,SNMP,NFS 等。
經常使用的端口號
操做系統中,通常0-1024的端口都被默認使用了(0-1024不要動),儘可能使用8000以後的端口號。
應用程序 | FTP | TFTP | TELNET | SMTP | DNS | HTTP | SSH | MYSQL |
---|---|---|---|---|---|---|---|---|
熟知端口 | 21,20 | 69 | 23 | 25 | 53 | 80 | 22 | 3306 |
傳輸層協議 | TCP | UDP | TCP | TCP | UDP | TCP | TCP | TCP |
【問題1】爲何鏈接的時候是三次握手,關閉的時候倒是四次握手?
答:由於當Server端收到Client端的SYN鏈接請求報文後,能夠直接發送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。可是關閉鏈接時,當Server端收到FIN報文時,極可能並不會當即關閉SOCKET,因此只能先回復一個ACK報文,告訴Client端,"你發的FIN報文我收到了"。只有等到我Server端全部的報文都發送完了,我才能發送FIN報文,所以不能一塊兒發送。故須要四步握手。
【問題2】爲何TIME_WAIT狀態須要通過2MSL(最大報文段生存時間)才能返回到CLOSE狀態?
答:雖然按道理,四個報文都發送完畢,咱們能夠直接進入CLOSE狀態了,可是咱們必須假象網絡是不可靠的,有能夠最後一個ACK丟失。因此TIME_WAIT狀態就是用來重發可能丟失的ACK報文。在Client發送出最後的ACK回覆,但該ACK可能丟失。Server若是沒有收到ACK,將不斷重複發送FIN片斷。因此Client不能當即關閉,它必須確認Server接收到了該ACK。Client會在發送出ACK以後進入到TIME_WAIT狀態。Client會設置一個計時器,等待2MSL的時間。若是在該時間內再次收到FIN,那麼Client會重發ACK並再次等待2MSL。所謂的2MSL是兩倍的MSL(Maximum Segment Lifetime)。MSL指一個片斷在網絡中最大的存活時間,2MSL就是一個發送和一個回覆所需的最大時間。若是直到2MSL,Client都沒有再次收到FIN,那麼Client推斷ACK已經被成功接收,則結束TCP鏈接。
【問題3】爲何不能用兩次握手進行鏈接?
答:3次握手完成兩個重要的功能,既要雙方作好發送數據的準備工做(雙方都知道彼此已準備好),也要容許雙方就初始序列號進行協商,這個序列號在握手過程當中被髮送和確認。如今把三次握手改爲僅須要兩次握手,死鎖是可能發生的。做爲例子,考慮計算機S和C之間的通訊,假定C給S發送一個鏈接請求分組,S收到了這個分組,併發 送了確認應答分組。按照兩次握手的協定,S認爲鏈接已經成功地創建了,能夠開始發送數據分組。但是,C在S的應答分組在傳輸中被丟失的狀況下,將不知道S 是否已準備好,不知道S創建什麼樣的序列號,C甚至懷疑S是否收到本身的鏈接請求分組。在這種狀況下,C認爲鏈接還未創建成功,將忽略S發來的任何數據分 組,只等待鏈接確認應答分組。而S在發出的分組超時後,重複發送一樣的分組。這樣就造成了死鎖。
【問題4】若是已經創建了鏈接,可是客戶端忽然出現故障了怎麼辦?
TCP還設有一個保活計時器,顯然,客戶端若是出現故障,服務器不能一直等下去,白白浪費資源。服務器每收到一次客戶端的請求後都會從新復位這個計時器,時間一般是設置爲2小時,若兩小時尚未收到客戶端的任何數據,服務器就會發送一個探測報文段,之後每隔75秒鐘發送一次。若一連發送10個探測報文仍然沒反應,服務器就認爲客戶端出了故障,接着就關閉鏈接。
Socket是應用層與TCP/IP協議族通訊的中間軟件抽象層,它是一組接口。在設計模式中,Socket其實就是一個門面模式,它把複雜的TCP/IP協議族隱藏在Socket接口後面,對用戶來講,一組簡單的接口就是所有,讓Socket去組織數據,以符合指定的協議。
因此,咱們無需深刻理解tcp/udp協議,socket已經爲咱們封裝好了,咱們只須要遵循socket的規定去編程,寫出的程序天然就是遵循tcp/udp標準的。
服務器端先初始化Socket,而後與端口綁定(bind),對端口進行監聽(listen),調用accept阻塞,等待客戶端鏈接。在這時若是有個客戶端初始化一個Socket,而後鏈接服務器(connect),若是鏈接成功,這時客戶端與服務器端的鏈接就創建了。客戶端發送數據請求,服務器端接收請求並處理請求,而後把迴應數據發送給客戶端,客戶端讀取數據,最後關閉鏈接,一次交互結束。
# File-服務端.py import socket phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #tcp稱爲流式協議,udp稱爲數據報協議SOCK_DGRAM # phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) phone.bind(('127.0.0.1', 8081)) phone.listen(5) # 半鏈接池,限制的是請求數 print('start....') conn, client_addr = phone.accept() #(三次握手創建的雙向鏈接,(客戶端的ip,端口)) print(conn) print(client_addr) #五、通訊:收\發消息 data = conn.recv(1024) #最大接收的字節數 print('來自客戶端的數據', data) conn.send(data.upper()) #六、斷開鏈接 conn.close() #七、結束服務 phone.close()
# File-客戶端.py import socket phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print(phone) phone.connect(('127.0.0.1', 8081)) # 指定鏈接服務端ip和端口 #三、通訊:發\收消息 phone.send('hello'.encode('utf-8')) # phone.send(bytes('hello',encoding='utf-8')) data = phone.recv(1024) print(data) #四、關閉 phone.close()
# File-服務端.py import socket phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #tcp稱爲流式協議,udp稱爲數據報協議SOCK_DGRAM # phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) phone.bind(('127.0.0.1', 8080)) phone.listen(5) # 半鏈接池,限制的是請求數 print('start....') while True: # 鏈接循環 conn, client_addr = phone.accept() #(三次握手創建的雙向鏈接,(客戶端的ip,端口)) # print(conn) print('已經有一個鏈接創建成功', client_addr) #五、通訊:收\發消息 while True: # 通訊循環 try: print('服務端正在收數據...') data = conn.recv(1024) #最大接收的字節數,沒有數據會在原地一直等待收,即發送者發送的數據量必須>0bytes # print('===>') if len(data) == 0: break #在客戶端單方面斷開鏈接,服務端纔會出現收空數據的狀況 print('來自客戶端的數據', data) conn.send(data.upper()) except ConnectionResetError: break #六、斷開鏈接 conn.close() #七、中止服務 phone.close()
# File-客戶端.py import socket phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) phone.connect(('127.0.0.1', 8080)) # 指定鏈接服務端ip和端口 #三、通訊:發\收消息 while True: # 通訊循環 msg = input('>>: ').strip() #msg='' if len(msg) == 0: continue phone.send(msg.encode('utf-8')) # print('has send----->') data = phone.recv(1024) # print('has recv----->') print(data) #四、斷開鏈接 phone.close()