網絡基礎概覽html
socket概覽python
socket模塊—TCP/UDP的實現mysql
osi七層協議各層主要的協議編程
# 物理層傳輸電信號1010101010 # 數據鏈路層,以太網協議,arp協議。對這些信號進行分組,同時規範了分組形式--以太網協議,頭部是mac地址中間是信息, # 網絡層:ip協議,arp協議幫忙找到mac地址,ip,子網掩碼,網關(下面有一些簡單歸納) # 傳輸層:tcp協議,udp協議 # (socket)就是一組接口,將複雜的tcp協議和udp協議隱藏在一組接口後面,用socket去組織數據,在用戶來看複雜的協議變爲簡單的接口 # 會話層,表示層,應用層 #應用層加tcp/UDP報頭,加IP報頭,加mac地址報頭,而後用電信號發出去 #arp協議:A機器把請求經過交換機經過廣播的方式查找B計算機,判斷是否是本身的IP地址,不是的話丟棄,是的話返回計算機對應的mac地址給交換機, #交換機再經過單播的方式,返回給A機器 # ,若是不在同一個網段,再經過網關去找目標ip #socket分類: #基於文件類型的套接字家族: AF_UNIX #基於網絡類型的套接字家族: AF_INET 還有 AF_INET6被用於ipv6 #IP 端口 :在同一臺機器上,同一時間,只能有一個程序,佔用同一個端口 #TCP:可靠的,面向鏈接的,(長鏈接),速度相對慢的 # UDP協議:不可靠,無鏈接,效率慢 #報文 數據包10101010就是報文 #咱們在網絡上傳輸的全部數據,都叫數據包,數據包裏全部的數據都叫報文 #報文裏不止有數據 還有 ip地址,mac地址,端口號,全部的報文都有報頭,是各個協議規定的
# tcp協議 # 全雙工的通訊協議:雙方均可以收發信息 # 一旦鏈接創建起來,那麼鏈接兩端的機器可以隨意互相通訊 # 面向鏈接的通訊方式 # 數據安全不容易丟失 # 創建鏈接的 三次握手 ****** 創建了全雙工通訊,我問你,你回答我順便問我,我回答你 三次握手 # 斷開鏈接的 四次揮手 ****** #全雙工通訊,要一方發起關閉請求,另外一方迴應關閉,而後達成關閉一條但雙工 #而後另外一方發起關閉請求,這一方迴應關閉,達到關閉全雙工的目的,必需要進行 兩次的 發起迴應
# 物理層傳輸電信號1010101010 # 數據鏈路層,以太網協議,arp協議。對這些信號進行分組,同時規範了分組形式--以太網協議,頭部是mac地址中間是信息, # 網絡層:ip協議,arp協議幫忙找到mac地址,ip,子網掩碼,網關(下面有一些簡單歸納) # 傳輸層:tcp協議,udp協議 # (socket)就是一組接口,將複雜的tcp協議和udp協議隱藏在一組接口後面,用socket去組織數據,在用戶來看複雜的協議變爲簡單的接口 # 會話層,表示層,應用層 #應用層加tcp/UDP報頭,加IP報頭,加mac地址報頭,而後用電信號發出去 #arp協議:A機器把請求經過交換機經過廣播的方式查找B計算機,判斷是否是本身的IP地址,不是的話丟棄,是的話返回計算機對應的mac地址給交換機, #交換機再經過單播的方式,返回給A機器 # ,若是不在同一個網段,再經過網關去找目標ip #socket分類: #基於文件類型的套接字家族: AF_UNIX #基於網絡類型的套接字家族: AF_INET 還有 AF_INET6被用於ipv6 #IP 端口 :在同一臺機器上,同一時間,只能有一個程序,佔用同一個端口 #TCP:可靠的,面向鏈接的,(長鏈接),速度相對慢的 # UDP協議:不可靠,無鏈接,效率慢 #報文 數據包10101010就是報文 #咱們在網絡上傳輸的全部數據,都叫數據包,數據包裏全部的數據都叫報文 #報文裏不止有數據 還有 ip地址,mac地址,端口號,全部的報文都有報頭,是各個協議規定的 # qq 微信 飛秋 網遊 微博 歪歪 _基於應用的網絡程序 # 百度 微博 知乎 博客園 網易 _基於瀏覽器的網絡程序 # 網絡編程中的 - C/S架構 # c client 客戶端 # s server 服務端 # 網絡編程中的 - B/S架構 # b broser 瀏覽器 # s server 服務端 # 不須要額外的安裝客戶端了,只須要一個網址就能夠訪問 # 輕量級 - 使用成本低 # B/S架構是C/S架構的一種特殊形式 # 手機上 : 瀏覽器 app # 兩個py程序想要通訊 # 寫文件 # 在不一樣機器上的兩個py程序之間想要通訊 # 網絡 # 網絡的發展史 # 網卡\網口 # 兩臺機器之間 插上網線就能夠通訊 # 網卡上 - mac地址 # ip地址 # 是4個點分十進制 - ipv4協議 # 0.0.0.0 - 255.255.255.255 # 127.0.0.1 本機 # 內網字段 192.168.**** # 10.**** # 172.*** # 6個點分十進制 - ipv6協議 # 0.0.0.0.0.0 - 255.255.255.255.255.255 # 交換機 # 廣播 # 單播 # 組播 # arp協議 : 經過IP地址獲取某一臺機器的mac地址 # 子網掩碼 # 子網掩碼 和 ip地址進行 按位 與 運算 就能得出一個機器所在的網段 # 192.168.21.36 # 11000000.10101000.00010101.00100100 #111111 # 255.255.255.0 255.255.0.0 # 11111111.11111111.11111111.00000000 #22222 1和2兩處按位與 # 11000000.10101000.00010101.00000000 #局域網的網段 # 192.168.21.0 網段 #IP協議做用兩個,一個是爲每一臺計算機分配ip地址,二是肯定哪些地址在同一個網段 # 網關地址 : 整個局域網中的機器能溝經過網關ip與外界通訊 # 網段 : 子網掩碼 和 ip地址進行 按位 與 運算 # 端口 : 0-65535 # 8000-酷狗音樂 22-ssh 3306-mysql # python 網絡應用 8000 # ip地址+端口號 : 在全網找到惟一的一臺機器+惟一的應用 # 咱們選擇端口 : 8000以後 # tcp協議 # 全雙工的通訊協議:雙方均可以收發信息 # 一旦鏈接創建起來,那麼鏈接兩端的機器可以隨意互相通訊 # 面向鏈接的通訊方式 # 數據安全不容易丟失 # 創建鏈接的 三次握手 ****** 創建了全雙工通訊,我問你,你回答我順便問我,我回答你 三次握手 # 斷開鏈接的 四次揮手 ****** #全雙工通訊,要一方發起關閉請求,另外一方迴應關閉,而後達成關閉一條但雙工 #而後另外一方發起關閉請求,這一方迴應關閉,達到關閉全雙工的目的,必需要進行 兩次的 發起迴應
Socket是應用層與TCP/IP協議族通訊的中間軟件抽象層,它是一組接口。在設計模式中,Socket其實就是一個門面模式,它把複雜的TCP/IP協議族隱藏在Socket接口後面,對用戶來講,一組簡單的接口就是所有,讓Socket去組織數據,以符合指定的協議。瀏覽器
其實站在你的角度上看,socket就是一個模塊。咱們經過調用模塊中已經實現的方法創建兩個進程之間的鏈接和通訊。 也有人將socket說成ip+port,由於ip是用來標識互聯網中的一臺主機的位置,而port是用來標識這臺機器上的一個應用程序。 因此咱們只要確立了ip和port就能找到一個應用程序,而且使用socket模塊來與之通訊。 3.套接字(socket)的發展史 套接字起源於 20 世紀 70 年代加利福尼亞大學伯克利分校版本的 Unix,即人們所說的 BSD Unix。 所以,有時人們也把套接字稱爲「伯克利套接字」或「BSD 套接字」。一開始,套接字被設計用在同 一臺主機上多個應用程序之間的通信。這也被稱進程間通信,或 IPC。套接字有兩種(或者稱爲有兩個種族),分別是基於文件型的和基於網絡型的。 基於文件類型的套接字家族 套接字家族的名字:AF_UNIX unix一切皆文件,基於文件的套接字調用的就是底層的文件系統來取數據,兩個套接字進程運行在同一機器,能夠經過訪問同一個文件系統間接完成通訊 基於網絡類型的套接字家族 套接字家族的名字:AF_INET (還有AF_INET6被用於ipv6,還有一些其餘的地址家族,不過,他們要麼是隻用於某個平臺,要麼就是已經被廢棄,或者是不多被使用,或者是根本沒有實現,全部地址家族中,AF_INET是使用最普遍的一個,python支持不少種地址家族,可是因爲咱們只關心網絡編程,因此大部分時候我麼只使用AF_INET)
TCP(Transmission Control Protocol)可靠的、面向鏈接的協議(eg:打電話)、傳輸效率低全雙工通訊(發送緩存&接收緩存)、面向字節流。使用TCP的應用:Web瀏覽器;電子郵件、文件傳輸程序。
UDP(User Datagram Protocol)不可靠的、無鏈接的服務,傳輸效率高(發送前時延小),一對1、一對多、多對1、多對多、面向報文,盡最大努力服務,無擁塞控制。使用UDP的應用:域名系統 (DNS);視頻流;IP語音(VoIP)。
socket模塊中TCP/UDP的實現:
基於TCP協議的socket:
import socket sk = socket.socket() #買電話,建立一個socket對象 # sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #買電話 網絡類型的socket類型和tcp #默認值def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None): #type=socket.SOCK_DARAM,UDP協議 datagram數據報文的縮寫 sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #避免服務重啓的時候出現 誤 OSError:address already in use #sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) sk.bind(('127.0.0.1',8080)) #綁定電話卡,bind方法,接受一個元組 元組裏是 (ip,port) sk.listen() #監聽,看誰要給我打電話 #括號內能夠放參數,好比 listen(5)只容許接收5個請求,就是說這裏 backlog-半連接池 大小是5,超過5個其餘請求就進不來了 #防止黑客用大量的虛擬客戶端訪問服務端即洪水攻擊,來佔滿backlog,讓其餘客戶端進不來,其中一個辦法就是擴大backlog的空間 conn,addr = sk.accept() #獲取connection 和 address 這裏conn 和addr 是兩個變量,不過通用都這麼寫 #這裏conn就是三次握手的鏈接 ret = conn.recv(1024) #接收遠方來的電話的信息,並設定要接收多少大小,2048,4096,222,隨便你設,通常是1024 print(ret) conn.send(b'hi') #接收到信息後,要回饋 ret = conn.recv(1024) print(ret.decode('utf-8')) conn.send('收到'.encode('utf-8')) conn.close() #掛電話 sk.close() #關手機 #有收必有發,收發必相等 # sever ----- client # send ----- recv # send ----- recv # recv ----- send #sever有一個send,client就要有一個receive,也能夠連續send兩次或者屢次,client一樣也要receive兩次或者屢次 #兩邊的send和recv必定是對應的,不能只接不收,不能只收不接 #正由於tcp這個收發特性,保證了他是可靠鏈接 # import socket # import time # sk = socket.socket() #建立一個socket對象 # #sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #默認值def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None): #type=socket.SOCK_DARAM,UDP協議 # # sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # sk.bind(('127.0.0.1',8898)) #給sever端綁定一個ip和端口 # sk.listen() #listen括號內放數值 指backlog,默認指的是不限定訪問人數 # conn,addr = sk.accept() #完成了三次握手,conn獲取到一個客戶端的連接 # #程序走在這會阻塞,等待客戶端鏈接 # # while True: # ret = conn.recv(1024).decode('utf-8') #recv又是一個阻塞點,直到收到一個客戶端發來的消息 # print(ret) # time_stamp = str(time.ctime(eval(ret))) # conn.send(bytes(time_stamp,encoding='utf-8')) # # conn.close() #關閉鏈接 # sk.close() #若是不關閉還會繼續接收
import socket sk = socket.socket() sk.connect(('127.0.0.1',8080)) #注意這裏不能用 bind,由於同一個端口,同一時間同一臺計算機只能綁定一個 sk.send(b'hello') # sk.send('你好'.encode('utf-8')) #b'hello' ret = sk.recv(1024) print(ret) sk.send(bytes('中午吃什麼',encoding='utf-8')) ret2 = sk.recv(1024) print(ret2.decode('utf-8')) sk.close() #有收必有發,收發必相等 #若是出現錯誤 OSError:address already in use #就是由於系統還沒關閉通訊,或者沒有寫關閉語句
小練習:
1.基於tcp的聊天練習
import socket,time sk = socket.socket() sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) sk.bind(('127.0.0.1',8898)) sk.listen() conn,addr = sk.accept() print(addr) while True: ret = conn.recv(1024).decode('utf-8') print(ret) if ret == 'bye': conn.send(b'bye') break info = input('>>> ')+' '+str(time.strftime('%Y-%m-%d %X')) conn.send(bytes(info,encoding='utf-8')) conn.close() sk.close()
import socket,time sk = socket.socket() sk.connect(('127.0.0.1',8898)) print(time.strftime('%Y-%m-%d %X')) while True: info = input('>>> ')+' '+str(time.strftime('%Y-%m-%d %X')) sk.send(bytes(info,encoding='utf-8')) ret = sk.recv(1024).decode('utf-8') print(ret) if ret == 'bye': sk.send(b'bye') break sk.close()
2.基於TCP的記錄時間練習
import socket import time sk = socket.socket() #建立一個socket對象 # sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) sk.bind(('127.0.0.1',8898)) #給sever端綁定一個ip和端口 sk.listen() #listen括號內放數值 指backlog,默認指的是不限定訪問人數 conn,addr = sk.accept() #完成了三次握手,conn獲取到一個客戶端的連接 #程序走在這會阻塞,等待客戶端鏈接 while True: ret = conn.recv(1024).decode('utf-8') #recv又是一個阻塞點,直到收到一個客戶端發來的消息 print(ret) time_stamp = str(time.ctime(eval(ret))) conn.send(bytes(time_stamp,encoding='utf-8')) conn.close() #關閉鏈接 sk.close() #若是不關閉還會繼續接收
import socket import time sk = socket.socket() sk.connect(('127.0.0.1',8898)) while True: ret = str(time.time()) sk.send(bytes(ret,encoding='utf-8')) time_struct = sk.recv(1024).decode('utf-8') print(time_struct) time.sleep(5) sk.close()
基於UDP的socket:
#UDP是必需要等客戶端主動發信息的,即被動的等待信息
#TCP主要客戶端鏈接,鏈接後服務器和客戶端均可以主動發信息
#客戶端發送消息的同時,還會自帶地址信息
#消息回覆的時候,不只須要發送消息,還須要把對方的地址填寫在內
import socket sk = socket.socket(type=socket.SOCK_DGRAM) sk.bind(('127.0.0.1',8890)) msg,addr = sk.recvfrom(1024) print(msg.decode('utf-8')) sk.sendto(b'hi',addr) sk.close()
import socket sk = socket.socket(type=socket.SOCK_DGRAM) ip_port = ('127.0.0.1',8890) sk.sendto(b'hello',ip_port) ret,addr = sk.recvfrom(1024) print(ret.decode('utf-8')) sk.close() #UDP不須要進行監聽,也不須要創建鏈接 #UDP是必需要等客戶端主動發信息的,即被動的等待信息 #TCP主要客戶端鏈接,鏈接後服務器和客戶端均可以主動發信息 #客戶端發送消息的同時,還會自帶地址信息 #消息回覆的時候,不只須要發送消息,還須要把對方的地址填寫在內
小練習:
1.udp實現的聊天兒
import socket sk = socket.socket(type=socket.SOCK_DGRAM) # sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) sk.bind(('127.0.0.1',8803)) while True: msg,addr = sk.recvfrom(1024) print(msg.decode('utf-8')) info = ('\033[34msever: \033'+input('>>> ')).encode('utf-8') sk.sendto(info,addr) sk.close()
import socket sk = socket.socket(type=socket.SOCK_DGRAM) ip_port = ('127.0.0.1',8803) while True: info = ('\033[31mww: \033[0m' + input('>>>> ')).encode('utf-8') sk.sendto(info,ip_port) msg,addr = sk.recvfrom(1024) print(msg.decode('utf-8')) sk.close()
2.udp更新時間
import socket import time sk = socket.socket(type=socket.SOCK_DGRAM) sk.bind(('127.0.0.1',8800)) msg,addr = sk.recvfrom(1024) print(addr) ret = msg.decode('utf-8') print(ret) ret2 = time.strftime(ret) sk.sendto(ret2.encode('utf-8'),addr) sk.close()
import socket sk = socket.socket(type=socket.SOCK_DGRAM) ip_port = ('127.0.0.1',8800) time_format = '%Y-%m-%d %X %a' sk.sendto(time_format.encode('utf-8'),ip_port) msg,addr = sk.recvfrom(1024) print(addr) print(msg.decode('utf-8')) sk.close()
# TCP協議屬於 : 傳輸層 # 面向鏈接 可靠的 字節流傳輸 長鏈接 # UDP協議屬於 : 傳輸層 # 面向數據包的 無鏈接的 不可靠的 速度快 不佔用鏈接 #UDP不會黏包,可是udp會丟包 #tcp會黏包,可是不會丟包 # 黏包成因: # TCP(transport control protocol,傳輸控制協議)是面向鏈接的,面向流的,提供高可靠性服務。 # 收發兩端(客戶端和服務器端)都要有一一成對的socket,所以,發送端爲了將多個發往接收端的包,更有效的發到對方, # 使用了優化方法(Nagle算法),將屢次間隔較小且數據量小的數據,合併成一個大的數據塊,而後進行封包。 # 這樣,接收端,就難於分辨出來了,必須提供科學的拆包機制。 即面向流的通訊是無消息保護邊界的。 # 當發送端緩衝區的長度大於網卡的MTU時,tcp會將此次發送的數據拆成幾個數據包發送出去。 # MTU是Maximum Transmission Unit的縮寫。意思是網絡上傳送的最大數據包。MTU的單位是字節。 # 大部分網絡設備的MTU都是1500。若是本機的MTU比網關的MTU大,大的數據包就會被拆開來傳送, # 這樣會產生不少數據包碎片,增長丟包率,下降網絡速度。 # 1.是由於tcp的拆包機制,使得消息沒有邊界 # 2.當發送端緩衝區的長度大於網卡的MTU時,產生了數據包碎片 #UDP不須要進行監聽,也不須要創建鏈接 #UDP是必需要等客戶端主動發信息的,即被動的等待信息 #TCP主要客戶端鏈接,鏈接後服務器和客戶端均可以主動發信息 #客戶端發送消息的同時,還會自帶地址信息 #消息回覆的時候,不只須要發送消息,還須要把對方的地址填寫在內 #有收必有發,收發必相等 (當收發不相等時候,TCP黏包,UDP丟包。若是len(發送)>len(接收)TCP會產生黏包, UDP會直接報錯,) # sever ----- client # send ----- recv # send ----- recv # recv ----- send #sever有一個send,client就要有一個receive,也能夠連續send兩次或者屢次,client一樣也要receive兩次或者屢次 #兩邊的send和recv必定是對應的,不能只接不收,不能只收不接 #正由於tcp這個收發特性,保證了他是可靠鏈接 #注意send不能發數字,要轉爲str # recv在本身這端的緩衝區爲空時,阻塞 # recvfrom在本身這端的緩衝區爲空時,就接收空