咱們瞭解的程序之間通信的應用可分爲兩種:python
第一種是應用類:qq、微信、百度網盤、騰訊視頻這一類是屬於須要安裝的桌面應用。web
第二種是web類:好比百度、知乎、博客園等使用瀏覽器訪問就能夠直接使用的應用。編程
這些應用的本質其實都是兩個程序之間的通信,而這兩個分類又對應了兩個軟件開發的架構。設計模式
C/S即:Client與Server ,中文意思:客戶端與服務器端架構,這種架構也是從用戶層面(也能夠是物理層面)來劃分的。瀏覽器
這裏的客戶端通常泛指客戶端應用程序EXE,程序須要先安裝後,才能運行在用戶的電腦上,對用戶的電腦操做系統環境依賴較大。緩存
B/S即:Browser與Server,中文意思:瀏覽器端與服務器端架構,這種架構是從用戶層面來劃分的。服務器
Browser瀏覽器,其實也是一種Client客戶端,只是這個客戶端不須要你們去安裝什麼應用程序,只需在瀏覽器上經過HTTP請求服務器端相關的資源(網頁資源),客戶端Browser瀏覽器就能進行增刪改查。微信
須知一個完整的計算機系統是由硬件、操做系統、應用軟件三者組成,具有了這三個條件,一臺計算機系統就能夠本身跟本身玩了(打個單機遊戲,玩個掃雷啥的)。網絡
若是你要跟別人一塊兒玩,那你就須要上網了,什麼是互聯網?架構
互聯網的核心就是由一堆協議組成,協議就是標準,好比全世界人通訊的標準是英語,若是把計算機比做人,互聯網協議就是計算機界的英語。全部的計算機都學會了互聯網協議,那全部的計算機都就能夠按照統一的標準去收發信息從而完成通訊了。
人們按照分工不一樣把互聯網協議從邏輯上劃分了層級:
首先,程序必需要啓動,其次,必須有這臺機器的地址,咱們都知道咱們人的地址大概就是國家\省\市\區\街道\樓\門牌號這樣字。那麼每一臺聯網的機器在網絡上也有本身的地址,它的地址是怎麼表示的呢?
就是使用一串數字來表示的,例如:192.168.0.1
IP地址是指互聯網協議地址(英語:Internet Protocol Address,又譯爲網際協議地址),是IP Address的縮寫。IP地址是IP協議提供的一種統一的地址格式,它爲互聯網上的每個網絡和每一臺主機分配一個邏輯地址,以此來屏蔽物理地址的差別。 IP地址是一個32位的二進制數,一般被分割爲4個「8位二進制數」(也就是4個字節)。IP地址一般用「點分十進制」表示成(a.b.c.d)的形式,其中,a,b,c,d都是0~255之間的十進制整數。例:點分十進IP地址(100.4.5.6),其實是32位二進制數(01100100.00000100.00000101.00000110)。
"端口"是英文port的意譯,能夠認爲是設備與外界通信交流的出口。
Windows查看端口占用狀況:
netstat -aon|findstr "49157"
Socket是應用層與TCP/IP協議族通訊的中間軟件抽象層,它是一組接口。在設計模式中,Socket其實就是一個門面模式,它把複雜的TCP/IP協議族隱藏在Socket接口後面,對用戶來講,一組簡單的接口就是所有,讓Socket去組織數據,以符合指定的協議。
其實站在你的角度上看,socket就是一個模塊。咱們經過調用模塊中已經實現的方法創建兩個進程之間的鏈接和通訊。 也有人將socket說成ip+port,由於ip是用來標識互聯網中的一臺主機的位置,而port是用來標識這臺機器上的一個應用程序。 因此咱們只要確立了ip和port就能找到一個應用程序,而且使用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)。
tcp是基於連接的,必須先啓動服務端,而後再啓動客戶端去連接服務端
server端:
import socket sk = socket.socket() sk.bind(('127.0.0.1',8898)) #把地址綁定到套接字 sk.listen() #監聽連接 conn,addr = sk.accept() #接受客戶端連接 ret = conn.recv(1024) #接收客戶端信息 print(ret) #打印客戶端信息 conn.send(b'hi') #向客戶端發送信息 conn.close() #關閉客戶端套接字 sk.close() #關閉服務器套接字(可選)
client端:
import socket sk = socket.socket() # 建立客戶套接字 sk.connect(('127.0.0.1',8898)) # 嘗試鏈接服務器 sk.send(b'hello!') ret = sk.recv(1024) # 對話(發送/接收) print(ret) sk.close() # 關閉客戶套接字
可能遇到的問題:
解決方法:
#加入一條socket配置,重用ip和端口 import socket from socket import SOL_SOCKET,SO_REUSEADDR sk = socket.socket() sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加 sk.bind(('127.0.0.1',8898)) #把地址綁定到套接字 sk.listen() #監聽連接 conn,addr = sk.accept() #接受客戶端連接 ret = conn.recv(1024) #接收客戶端信息 print(ret) #打印客戶端信息 conn.send(b'hi') #向客戶端發送信息 conn.close() #關閉客戶端套接字 sk.close() #關閉服務器套接字(可選)
server端:
import socket udp_sk = socket.socket(type=socket.SOCK_DGRAM) #建立一個服務器的套接字 udp_sk.bind(('127.0.0.1',9000)) #綁定服務器套接字 msg,addr = udp_sk.recvfrom(1024) print(msg) udp_sk.sendto(b'hi',addr) # 對話(接收與發送) udp_sk.close() # 關閉服務器套接字
client端:
import socket ip_port=('127.0.0.1',9000) udp_sk=socket.socket(type=socket.SOCK_DGRAM) udp_sk.sendto(b'hello',ip_port) back_msg,addr=udp_sk.recvfrom(1024) print(back_msg.decode('utf-8'),addr)
socket.socket(family=AF_INET,type=SOCK_STREAM,proto=0,fileno=None)
建立socket對象的參數說明: