一、網絡基礎
網絡建立的目的是為了資料互動(通信)
如何實作通信:
1.建立好底層的實體連接配接媒體
2.有一套統一的通信标準,稱之為網際網路協定
1.osi七層協定
網際網路協定按照功能的不同分為osi七層或tcp/ip五層或tcp/ip四層
每層運作的常見實體裝置
2.tcp/ip五層協定模型講解
2.1實體層:主要是基于電器特性發送高低電壓(電信号),高電壓對應數字1,低電壓對應數字0
2.2資料鍊路層:定義了電信号的分組方式,由于單純的0和1并沒有任何意義,必須規定電信号多少位一組,每組什麼意思
以太網協定:
早期每個公司都有自己的分組方式,後來形成統一的标準,即以太網協定Ethernet
Ethernet規定
1.一組電信号構成一個資料包,叫做‘幀’,每一資料幀分成:報頭head和資料data兩部分
2.報頭(head):固定位元組數,裡面包含發送者,接收者,資料類型。資料(data):資料包的具體内容
mac位址
head中包含的源和目标位址的由來:以太網規定接入internet的裝置都必須具備網卡,發送位址和接收位址都是通過網卡來的
每塊網卡出廠時都被燒制上一個唯一的mac位址,前6位是廠商編号,後6位是流水線号
廣播:
有了mac位址,同一網絡内的兩台計算機就可以通信了
2.3網絡層:不同網絡内想要通信,光靠Ethernet、mac位址和廣播并不可行,是以引入一套新的位址用來區分不同的網絡,這套位址就叫網絡位址
ip協定:
規定網絡位址的協定叫ip協定,它定義的位址稱為ip位址,廣泛采用v4版本即ipv4,它規定網絡位址由32位2進制表示
範圍為0.0.0.0 ---255.255.255.255
ip位址分為兩部分
網絡部分:辨別子網
主機部分:辨別主機
子網路遮罩:
形式上等同于ip位址,也是32位二進制,網絡部分全部為1,主機部分全為0。
知道子網路遮罩我們就能判斷,任意兩個ip位址是否處在同一個子網絡。方法是将兩個ip位址分别進行AND運算(兩個都為1運算結果為1,否則為0),比較結果是否相同,如果相同的話就表明他們是在一個子網絡中,否則就不是
總結ip協定的作用:1.為每台計算機配置設定ip位址,2确定這些位址是不是在同一個子網絡中。
ARP協定
廣播的方式發送資料包,擷取目标主機的mac位址
2.4傳輸層:網絡層的ip幫我們區分子網,以太網層的mac幫我們找到主機,傳輸層建立端口到端口的通信,端口就是應用程式與網關關聯的編号 端口範圍0-65535, 0-1023位系統占用端口
tcp協定:可靠傳輸,tcp資料包沒有長度限制,必須等到有回應才會繼續發送
udp協定:不可靠傳輸,不管有沒有收到響應隻管發送
tcp的三次握手
注:TCP的TIME_WAIT需要等待2MSL,當TCP的一端發起主動關閉,三次揮手完成後發送第四次揮手的ACK包後就進入這個狀态,等待2MSL時間主要目的是:防止最後一個ACK包對方沒有收到,那麼對方在逾時後将重發第三次握手的FIN包,主動關閉端接到重發的FIN包後可以再發一個ACK應答包。在TIME_WAIT狀态時兩端的端口不能使用,要等到2MSL時間結束才可以繼續使用。當連接配接處于2MSL等待階段時任何遲到的封包段都将被丢棄。MSL即Maximum Segment Lifetime,就是最大封包生存時間,是任何封包在網絡上的存在的最長時間,超過這個時間封包将被丢棄。
常見面試題:為什麼建立連結是三次握手,不是二次,四次,關閉連結卻是四次不是其它
這是因為服務端在LISTEN狀态下,收到建立連接配接請求的SYN封包後,把ACK和SYN放在一個封包裡發送給用戶端。而關閉連接配接時,當收到對方的FIN封包時,僅僅表示對方不再發送資料了但是還能接收資料,己方也未必全部資料都發送給對方了,是以己方可以立即close,也可以發送一些資料給對方後,再發送FIN封包給對方來表示同意現在關閉連接配接,是以,己方ACK和FIN一般都會分開發送。
2.5應用層:規定應用程式的資料格式
二、socket介紹
socket是應用層與tcp/ip協定通信的中間軟體抽象層,它是一組接口,它吧複雜的TCP/IP協定隐藏在socket接口後面。
基于檔案類型的套接字家族:
套接字家族的名字:AF_UNIX
unix一切皆檔案,基于檔案的套接字調用的就是底層的檔案系統來取資料,兩個套接字程序運作在同一機器,可以通過通路同一個檔案系統間接完成通信
基于網絡類型的套接字家族:
套接字家族的名字:AF_INET
AF_INET被用于ipv4,AF_INET6被用于ipv6
三、套接字使用
import socket
socket.socket(socket_family,socket_type,protocal=0)
socket_family 可以是 AF_UNIX 或 AF_INET。socket_type 可以是 SOCK_STREAM 或 SOCK_DGRAM。protocol 一般不填,預設值為 0。
擷取tcp/ip套接字
tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
擷取udp/ip套接字
udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
由于 socket 子產品中有太多的屬性。我們在這裡破例使用了'from module import *'語句。使用 'from socket import *',我們就把 socket 子產品裡的所有屬性都帶到我們的命名空間裡了,這樣能 大幅減短我們的代碼。
例如tcpSock = socket(AF_INET, SOCK_STREAM)
用戶端套接字函數
s.connect() 主動初始化TCP伺服器連接配接
s.connect_ex() connect()函數的擴充版本,出錯時傳回出錯碼,而不是抛出異常
公共用途的套接字函數
s.recv() 接收TCP資料
s.send() 發送TCP資料(send在待發送資料量大于己端緩存區剩餘空間時,資料丢失,不會發完)
s.sendall() 發送完整的TCP資料(本質就是循環調用send,sendall在待發送資料量大于己端緩存區剩餘空間時,資料不丢失,循環調用send直到發完)
s.recvfrom() 接收UDP資料
s.sendto() 發送UDP資料
s.getpeername() 連接配接到目前套接字的遠端的位址
s.getsockname() 目前套接字的位址
s.getsockopt() 傳回指定套接字的參數
s.setsockopt() 設定指定套接字的參數
s.close() 關閉套接字
面向鎖的套接字方法
s.setblocking() 設定套接字的阻塞與非阻塞模式
s.settimeout() 設定阻塞套接字操作的逾時時間
s.gettimeout() 得到阻塞套接字操作的逾時時間
面向檔案的套接字的函數
s.fileno() 套接字的檔案描述符
s.makefile() 建立一個與該套接字相關的檔案
基于tcp協定通信的套接字簡單
from socket import socket, AF_INET, SOCK_STREAM
# socket 套接字
# AF_INET IPv4
# SOCK_STREAM socket流
IP = "127.0.0.1"
PORT = 8888
ADDRESS = (IP, PORT)
BUFSIZE = 1024
print("伺服器開啟了")
# 1.建立伺服器socket對象
serSocket = socket(AF_INET, SOCK_STREAM)
# 2.設定伺服器位址
serSocket.bind(ADDRESS)
# 3.設定連接配接管理隊列
serSocket.listen(5)
# 4.建立用戶端伺服器連接配接
cliSocket, addr = serSocket.accept()
print(cliSocket)
print(addr)
# 5.收發資料
data = cliSocket.recv(BUFSIZE)
print(data.decode("utf-8"))
cliSocket.send("伺服器傳回的資料".encode("utf-8"))
# 6.斷開用戶端
cliSocket.close()
# 7.關閉伺服器
serSocket.close()
print("伺服器關閉了")
server
from socket import socket, AF_INET, SOCK_STREAM
IP = "127.0.0.1"
PORT = 8888
ADDRESS = (IP, PORT)
BUFSIZE = 1024
print("用戶端開啟了")
# 1.建立用戶端socket對象
cliSocket = socket(AF_INET, SOCK_STREAM)
# 2.連接配接伺服器位址
cliSocket.connect(ADDRESS)
print(cliSocket)
# 3.收發資料
cliSocket.send("用戶端發送的資料".encode("utf-8"))
data = cliSocket.recv(BUFSIZE)
print(data.decode("utf-8"))
# 4.關閉用戶端
cliSocket.close()
print("用戶端關閉了")
client
焚膏油以繼晷,恒兀兀以窮年。