假期(網絡編程)
阿新 • • 發佈:2018-02-15
str 組織 分類 toc 兩個 makefile 抽象層 客戶 分時
""" 一、客戶端/服務端架構: 1、硬件C/S架構(打印機) 2、軟件C/S架構 互聯網中處處都是CS架構,服務端與客戶端 CS架構與socket的關系 - 我們學習socket就是為了完成C/S架構的開發 二、OSI七層模型: 一個完整的計算機系統是由硬件、操作系統、應用軟件三者組成,一臺計算機只能自己玩自己,要想跟別人玩就需要上網了 互聯網的核心就是由一堆協議組成,協議就是標準,比如全世界人通信的標準是英語; 如果把計算機比做人,那麽互聯網協議就是計算機界的英語了,如果所有的計算機都學會了這門英語,那麽就可以互相通信了 為何學習socket一定要先學習互聯網協議: - 1、首先我們的目標是基於socket編程,來開發一款自己的cs架構軟件 - 2、其次cs架構軟件(軟件屬於應用層)是基於網絡進行通信的 - 3、網絡的核心即一堆協議,協議即標準,你想開發一款基於網絡通信的軟件,就必須遵循這些標準 三、socket層 socket層位於運輸層和應用層之間,即socket抽象層 四、socket是什麽? socket是應用層與TCP/IP協議族通信的中間軟件抽象層,它是一組接口。在設計模式中,socket其實就是一個門面模式,它吧復雜的 TCP/IP協議族隱藏在了socket接口的後面,對用戶來說,一組簡單的接口就是全部,讓socket去組織數據,以符合指定的協議 所以我們無需深入理解tcp/udp協議,socket已經幫我們封裝好了,我們只需要遵循socket的規定去編程,寫出的程序自然符合標準 - 也有人將socket說成是IP+port,IP是用來標識互聯網中的一臺主機的位置,而port是用來標識這臺主機上的一個應用程序,IP地址 配置到網卡上的,而port是應用程序開啟的,IP與port的綁定就標識了互聯網中獨一無二的應用程序 程序的pid是同一臺機器上不同進程或者線程的標識 五、套接字的分類: - 基於文件類型的套接字家族 套接字家族的名字:AF_UNIX unix一切皆文件,基於文件的套接字調用的就是底層文件系統來取數據,兩個套接字進程運行在同一機器,可以通過訪問同一個 間接完成通信。 - 基於網絡類型的套接字家族 套接字家族的名字:AF_INET ···所有的地址家族中,AF_INET是使用最廣泛的一個,python支持很多種地址家族,但是由於我們只關心網絡編程,所以我們 大部分時間都只是使用AF_INET 六、套接字的工作流程: 一個生活中的場景:你要給你前對象打電話,先撥號,前對象聽到電話鈴聲後拿起電話,這時候你倆就建立起來了不正當的鏈接,然後 就可以進行不正當的交易了。交易完成後,掛斷電話結束此次交談; 先從服務端說起,服務端先初始化socket,然後與端口綁定(bind),對端口進行監聽(listen),調用accept阻塞,等待客戶端鏈接 在這個時候如果有客戶端初始化一個socket,然後鏈接服務器(connect),如果鏈接成功,這時客戶端與服務端的鏈接就建立了。 客戶端發送數據請求,服務端接收請求並處理,然後把回應數據發送給客戶端,客戶端讀取數據,關閉鏈接,交互結束 - socket函數的用法 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 xxx import * 的語句導入,這樣就可以減少代碼量 eg:tcpsock = socket(AF_INET,SOCK_STREAM) - 服務端套接字函數 s.bind()綁定(主機,端口號)到套接字 s.listen()開始tcp監聽 s.accept()被動接受tcp客戶的連接,(阻塞式)等待連接的到來 - 客戶端套接字函數 c.connect()被動初始化tcp服務器連接 c.connect_ex() connect()函數的擴展版本,出錯時返回錯誤碼,而不是拋出異常 - 公共用途的套接字函數 s.recv()接受tcp數據 s.send()發送tcp數據(send在待發送數據量大於已緩存區剩余的空間時,數據丟失,不會發完) s.sendall()發送完整的tcp數據(本質就是循環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的套接字 tcp是基於鏈接的,必須先啟動服務端,然後再啟動客戶端去鏈接服務端 - tcp服務端: server = socket() #創建服務器套接字 server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) server.bind() #把地址綁定到套接字 server.listen() #監聽鏈接 while true: #服務器無限循環 client,addr = server.accept() #接受客戶端鏈接 while True: #通信循環 client.recv()/client.send() #接收與發送數據 client.close() #關閉客戶端套接字 server.close() #關閉服務器套接字 - tcp客戶端: client = socket() #創建客戶端套接字 client.connect() #嘗試鏈接服務器 while True: client.send()/client.recv() #發送/接收數據 client.close() #關閉客戶端套接字 八、基於udp的套接字 - udp服務端 server = socket() #創建服務器套接字 server.bind() #綁定套接字地址 while True: #服務器無線循環 client,addr = server.recvfrom()/server.sendto() #接收與發送數據 server.close() #關閉服務器套接字 - udp客戶端 client = socket() #創建客戶端套接字 while True: #通信循環 client.sendto()/client.recvfrom() #發送與接收數據 client.close() #關閉客戶端套接字 九、粘包現象(了解) 如果當我們用socket模擬cmd執行遠程命令時,有些數據太長,超過了1024個字節,一次接受不完,就會造成粘包 - 什麽是粘包? 只有tcp才有粘包現象,udp永遠不會粘包,因為udp是基於流收發數據的 所謂粘包的問題主要還是因為接收方不知道消息之間的界限,不知道一次性提取多少數據造成的 - 粘包的解決 - struct模塊 - 自定義報頭 - ··· - 什麽時候才會發生粘包? 發送端需要等緩沖區滿才發送出去,造成粘包(發送數據時間間隔很短,數據很小會喝到一起,產生粘包) 接收方不及時接收緩沖區的包,造成多個包接收產生粘包 - 了解 tcp是可靠傳輸,udp是不可靠傳輸 十、socketserver模塊 - 終極必殺技"""
假期(網絡編程)