兩臺計算機之間的通訊與兩我的打電話原理是同樣的.html
# 1. 首先要經過各類物理鏈接介質鏈接 # 2. 找準確對方計算機(準確到軟件)的位置 # 3. 經過統一的標準(通常子協議)進行數據的轉發 # 物理鏈接介質,這個是網絡工程師所考慮的,後面也會給你們簡單的講到,我們主要就是學習這統一的標準。 # 英語成爲世界上全部人通訊的統一標準,若是把計算機當作分佈於世界各地的人,那麼鏈接兩臺計算機之間的internet實際上就是一系列統一的標準,這些標準稱之爲互聯網協議,互聯網的本質就是一系列的協議,總稱爲‘互聯網協議’(Internet Protocol Suite). # 互聯網協議的功能:定義計算機如何接入internet,以及接入internet的計算機通訊的標準。
自從互聯網誕生以來,如今基本上全部的程序都是網絡程序,不多有單機版的程序了.前端
計算機網絡就是把各個計算機鏈接到一塊兒,讓網絡中的計算機能夠互相通訊。網絡編程就是如何在程序中實現兩臺計算機的通訊。python
舉個例子,當你使用瀏覽器訪問新浪網時,你的計算機就和新浪的某臺服務器經過互聯網鏈接起來了,而後,新浪的服務器把網頁內容做爲數據經過互聯網傳輸到你的電腦上。mysql
因爲你的電腦上可能不止瀏覽器,還有QQ、Skype、Dropbox、郵件客戶端等,不一樣的程序鏈接的別的計算機也會不一樣,因此,更確切地說,網絡通訊是兩臺計算機上的兩個進程之間的通訊。好比,瀏覽器進程和新浪服務器上的某個Web服務進程在通訊,而QQ進程是和騰訊的某個服務器上的某個進程在通訊。程序員
雖然你們如今對互聯網很熟悉,可是計算機網絡的出現比互聯網要早不少。redis
計算機爲了聯網,就必須規定通訊協議,早期的計算機網絡,都是由各廠商本身規定一套協議,IBM、Apple和Microsoft都有各自的網絡協議,互不兼容,這就比如一羣人有的說英語,有的說中文,有的說德語,說同一種語言的人能夠交流,不一樣的語言之間就不行了。sql
爲了把全世界的全部不一樣類型的計算機都鏈接起來,就必須規定一套全球通用的協議,爲了實現互聯網這個目標,互聯網協議簇(Internet Protocol Suite)就是通用協議標準。Internet是由inter和net兩個單詞組合起來的,原意就是鏈接「網絡」的網絡,有了Internet,任何私有網絡,只要支持這個協議,就能夠聯入互聯網。數據庫
由於互聯網協議包含了上百種協議標準,可是最重要的兩個協議是TCP和IP協議,因此,你們把互聯網的協議簡稱TCP/IP協議。django
通訊的時候,雙方必須知道對方的標識,比如發郵件必須知道對方的郵件地址。互聯網上每一個計算機的惟一標識就是IP地址,相似
123.123.123.123
。若是一臺計算機同時接入到兩個或更多的網絡,好比路由器,它就會有兩個或多個IP地址,因此,IP地址對應的其實是計算機的網絡接口,一般是網卡編程 IP協議負責把數據從一臺計算機經過網絡發送到另外一臺計算機。數據被分割成一小塊一小塊,而後經過IP包發送出去。因爲互聯網鏈路複雜,兩臺計算機之間常常有多條線路,所以,路由器就負責決定如何把一個IP包轉發出去。IP包的特色是按塊發送,途徑多個路由,但不保證能到達,也不保證順序到達。
IP地址其實是一個32位整數(稱爲IPv4),以字符串表示的IP地址如`192.168.0.1`其實是把32位整數按8位分組後的數字表示,目的是便於閱讀。 IPv6地址其實是一個128位整數,它是目前使用的IPv4的升級版,以字符串表示相似於`2001:0db8:85a3:0042:1000:8a2e:0370:7334`。 TCP協議則是創建在IP協議之上的。TCP協議負責在兩臺計算機之間創建可靠鏈接,保證數據包按順序到達。TCP協議會經過握手創建鏈接,而後,對每一個IP包編號,確保對方按順序收到,若是包丟掉了,就自動重發。 許多經常使用的更高級的協議都是創建在TCP協議基礎上的,好比用於瀏覽器的HTTP協議、發送郵件的SMTP協議等。 一個TCP報文除了包含要傳輸的數據外,還包含源IP地址和目標IP地址,源端口和目標端口。 端口有什麼做用?在兩臺計算機通訊時,只發IP地址是不夠的,由於同一臺計算機上跑着多個網絡程序。一個TCP報文來了以後,究竟是交給瀏覽器仍是QQ,就須要端口號來區分。每一個網絡程序都向操做系統申請惟一的端口號,這樣,兩個進程在兩臺計算機之間創建網絡鏈接就須要各自的IP地址和各自的端口號。 一個進程也可能與多個計算機創建連接,所以他會申請不少端口. 瞭解了TCP/IP協議的基本概念,IP地址和端口的概念,咱們就能夠開始進行網絡編程了。
客戶端英文名稱:Client,
瀏覽器英文名稱:Browser.
服務端英文名稱:Server.
C/S架構:基於客戶端與用戶端之間的架構。例如:QQ、微信、優酷、暴風影音等等。
B/S架構:基於C/S架構的一種特殊的C/S架構,瀏覽器與服務端之間的架構。
小結:CS響應速度快,安全性強,通常應用於局域網中,可是開發維護成本高;BS能夠實現跨平臺,客戶端零維護,可是個性化能力低,響應速度較慢。因此有些單位平常辦公應用BS,在實際生產中使用CS結構。
# C/S 架構 C: 客戶端 S: 服務端 # B/S 架構 B: 瀏覽器 S: 服務端 # C/S架構: 須要安裝一下才能使用 # client 客戶端: 咱們用的 須要安裝的 # server 服務端 # B/S架構: 百度 博客園 谷歌 碼雲 # browser 瀏覽器 # server 服務器 # b/s和c/s什麼關係? # B/S架構是C/S架構的一種 # C/S架構的好處 # 能夠離線使用/功能更完善/安全性更好 # B/S架構 # 不用安裝就可使用 # 統一PC端用戶的入口 # 手機端: 好像C/S架構比較火,其實否則,微信小程序,支付寶第三方接口都相似於B/S架構 # 目的都在於統一接口: 彙集用戶羣 # PC端: BS比較火 # 本質: B/S架構自己也是C/S架構
客戶端與服務端概念
# 服務端: 24小時不間斷提供服務,誰來我就服務誰 # 客戶端: 想體驗服務的時候,就去找服務端體驗服務
學習網絡編程能幹什麼
# 開發C/S架構的軟件
學習併發,數據庫,前端能幹什麼
# 開發B/S架構的軟件
網絡編程技術起源
# 絕大部分先進技術的興起基原本自於軍事,網絡編程這項技術來源於美國軍事,爲了實現數據的遠程傳輸.
人類實現遠程溝通交流的方式
# 插電話線的電話 # 插網線的大屁股電腦 # 插無線網卡的筆記本電腦 # 綜上咱們可以總結出第一個規律:要想實現遠程通訊第一個須要具有的條件就是: 物理鏈接介質 # 再來想人與人之間交流,中國人說中文,外國人說外語, # 那若是想實現不一樣國家的人之間無障礙溝通交流是否是得規定一個你們都能聽得懂的語言>>>英語 # 再回來看計算機領域,計算機之間要想實現遠程通訊除了須要有物理鏈接介質以外是否是也應該有一套公共的標準?這套標準就是 # >>>OSI七層協議(也叫OSI七層模型)
# 應用層 # 表示層 # 會話層 # 傳輸層 # 網絡層 # 數據鏈路層 # 物理鏈接層 # 也有人將其概括爲五層 # 應用層 # 傳輸層 # 網絡層 # 數據鏈路層 # 物理鏈接層
物理層由來: 上面提到,孤立的計算機之間要想一塊兒玩,就必須接入internet,言外之意就是計算機之間必須完成組網.
物理層功能: 主要是基於電路特性發送高低電壓(電信號),高電壓對應數字1,低電壓對應數字0
# 實現計算機之間物理鏈接,傳輸的數據都是010101的二進制 # 電信號工做原理: 點只有高低電平
光纖
雙絞線
數據鏈路層由來: 單純的電信號0和1沒有任何意義,必須規定電信號多少位一組,每組什麼意思.
數據鏈路層的功能: 定義了電信號的分組方式
以太網協議
早期的時候各個公司都有本身的分組方式,後來造成了統一的標準,即以太網協議ethernet
ethernet規定
一組電信號構成一個數據豹,叫作‘幀’
每一數據幀分紅:報頭head和數據data兩部分
Head | Data |
---|---|
報頭 | 數據 |
# head包含:(固定18個字節) # 發送者/源地址,6個字節 # 接收者/目標地址,6個字節 # 數據類型,6個字節 # data包含: (最短46字節,最長1500字節) # 數據包的具體內容 # head長度 + data長度 = 最短64字節,最長1518字節,超過限制就分片發送
mac地址
head中包含的源和目標地址由來:ethernet規定接入internet的設備都必須具有網卡,發送端和接收端的地址即是指網卡的地址,即mac地址
mac地址:每塊網卡出廠時都被燒製上一個世界惟一的mac地址,長度爲48位2進制,一般由12位16進制數表示(前六位是廠商編號,後六位是流水線號)
廣播
有了mac地址,同一網絡內的兩臺主機就能夠通訊了(一臺主機經過arp協議獲取另一臺主機的mac地址)
ethernet採用最原始的方式,廣播的方式進行通訊,即計算機通訊基本靠吼
# 1. 規定了二進制數據的分組方式 # 2. 規定了只要是接入互聯網的計算機,都必須有一塊網卡 # 網卡上刻有世界惟一的編號 # 每塊網卡出廠時都會被燒製上一個世界上惟一的mac地址 # 長度爲48位2進制,一般由12位16進制數表示(前六位是廠商編號,後六位是流水線號) # 咱們管網卡上刻有的編號叫電腦的>>>mac地址 # —–>上面的兩個規定其實就是 「以太網協議」! # 基於以太網協議通訊: 通訊基本靠吼!!! 弊端: 廣播風暴 # 交換機: 若是沒有交換機,你的電腦就變成了馬蜂窩,有了交換機吼,全部的電腦只須要一個網卡鏈接交換機,便可實現多臺電腦之間物理鏈接
網絡層由來:有了ethernet、mac地址、廣播的發送方式,世界上的計算機就能夠彼此通訊了,問題是世界範圍的互聯網是由
一個個彼此隔離的小的局域網組成的,那麼若是全部的通訊都採用以太網的廣播方式,那麼一臺機器發送的包全世界都會收到,
這就不只僅是效率低的問題了,這會是一種災難
上圖結論:必須找出一種方法來區分哪些計算機屬於同一廣播域,哪些不是,若是是就採用廣播的方式發送,若是不是,
就採用路由的方式(向不一樣廣播域/子網分發數據包),mac地址是沒法區分的,它只跟廠商有關
網絡層功能:引入一套新的地址用來區分不一樣的廣播域/子網,這套地址即網絡地址
IP協議:
ip地址分紅兩部分
注意:單純的ip地址段只是標識了ip地址的種類,從網絡部分或主機部分都沒法辨識一個ip所處的子網
例:172.16.10.1與172.16.10.2並不能肯定兩者處於同一子網
子網掩碼
所謂」子網掩碼」,就是表示子網絡特徵的一個參數。它在形式上等同於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協議的做用主要有兩個,一個是爲每一臺計算機分配IP地址,另外一個是肯定哪些地址在同一個子網絡。
ip數據包
ip數據包也分爲head和data部分,無須爲ip包定義單獨的欄位,直接放入以太網包的data部分
head:長度爲20到60字節
data:最長爲65,515字節。
而以太網數據包的」數據」部分,最長只有1500字節。所以,若是IP數據包超過了1500字節,它就須要分割成幾個以太網數據包,分開發送了。
以太網頭 | ip 頭 | ip數據 |
---|---|---|
ARP協議
arp協議由來:計算機通訊基本靠吼,即廣播的方式,全部上層的包到最後都要封裝上以太網頭,而後經過以太網協議發送,在談及以太網協議時候,我門瞭解到
通訊是基於mac的廣播方式實現,計算機在發包時,獲取自身的mac是容易的,如何獲取目標主機的mac,就須要經過arp協議
arp協議功能:廣播的方式發送數據包,獲取目標主機的mac地址
協議工做方式:每臺主機ip都是已知的
例如:主機172.16.10.10/24訪問172.16.10.11/24
一:首先經過ip地址和子網掩碼區分出本身所處的子網
場景 | 數據包地址 |
---|---|
同一子網 | 目標主機mac,目標主機ip |
不一樣子網 | 網關mac,目標主機ip |
二:分析172.16.10.10/24與172.16.10.11/24處於同一網絡(若是不是同一網絡,那麼下表中目標ip爲172.16.10.1,經過arp獲取的是網關的mac)
源mac | 目標mac | 源ip | 目標ip | 數據部分 | |
---|---|---|---|---|---|
發送端主機 | 發送端mac | FF:FF:FF:FF:FF:FF | 172.16.10.10/24 | 172.16.10.11/24 | 數據 |
三:這個包會以廣播的方式在發送端所處的自網內傳輸,全部主機接收後拆開包,發現目標ip爲本身的,就響應,返回本身的mac
# 規定了計算機都必須有一個ip地址 # ip地址特色:點分十進制 # 有兩個版本ipv4和ipv6 爲了可以兼容更多的計算機 # 最小:0.0.0.0 # 最大:255.255.255.255 # IP協議能夠跨局域網傳輸 # ip地址可以惟一標識互聯網中獨一無二的一臺機器! # [http://14.215.177.39/](http://14.215.177.39/)
傳輸層的由來:網絡層的ip幫咱們區分子網,以太網層的mac幫咱們找到主機,而後你們使用的都是應用程序,你的電腦上可能同時開啓qq,暴風影音,等多個應用程序,
那麼咱們經過ip和mac找到了一臺特定的主機,如何標識這臺主機上的應用程序,答案就是端口,端口即應用程序與網卡關聯的編號。
傳輸層功能:創建端口到端口的通訊
補充:端口範圍0-65535,0-1023爲系統佔用端口
tcp協議:
可靠傳輸,TCP數據包沒有長度限制,理論上能夠無限長,可是爲了保證網絡的效率,一般TCP數據包的長度不會超過IP數據包的長度,以確保單個TCP數據包沒必要再分割。
以太網頭 | ip 頭 | tcp頭 | 數據 |
---|---|---|---|
tcp報文
tcp三次握手和四次揮手
udp協議:
不可靠傳輸,」報頭」部分一共只有8個字節,總長度不超過65,535字節,正好放進一個IP數據包。
以太網頭 | ip頭 | udp頭 | 數據 |
---|---|---|---|
# TCP,UDP基於端口工做的協議! # 其實計算機之間通訊實際上是計算機上面的應用程序於應用之間的通訊 # 端口(port):惟一標識一臺計算機上某一個基於網絡通訊的應用程序 # 端口範圍:0~~65535(動態分配) # 注意:0~~1024一般是歸操做系統分配的端口號 # 一般狀況下,咱們寫的軟件端口號建議起在8000以後 # flask框架默認端口5000 # django框架默認端口8000 # mysql數據庫默認端口3306 # redis數據庫默認端口6379 # 注意:一臺計算機上同一時間一個端口號只能被一個應用程序佔用 # 小總結: # IP地址:惟一標識全世界接入互聯網的獨一無二的機器 # port端口號:惟一標識一臺計算機上的某一個應用程序 # ip+port :可以惟一標識全世界上獨一無二的一臺計算機上的某一個應用程序 # 補充: # arp協議:根據ip地址解析mac地址
應用層由來:用戶使用的都是應用程序,均工做於應用層,互聯網是開發的,你們均可以開發本身的應用程序,數據多種多樣,必須規定好數據的組織形式
應用層功能:規定應用程序的數據格式。
例:TCP協議能夠爲各類各樣的程序傳遞數據,好比Email、WWW、FTP等等。那麼,必須有不一樣協議規定電子郵件、網頁、FTP數據的格式,這些應用程序協議就構成了」應用層」。
# 三次握手四次揮手 # 三次握手建鏈接 # 四次揮手斷鏈接 # Tcp(語音聊天/視頻聊天),線下緩存高強電影\QQ遠程控制 # 須要先創建鏈接,而後才能通訊 # 佔用鏈接\可靠(消息不會丟失)\實時性高\慢 # UDP(發消息) - 在線播放視頻\QQ發消息\微信消息 # 不須要創建鏈接,就能夠通訊 # 不佔用鏈接\不可靠\消息由於網絡不穩定丟失\快
想實現網絡通訊,每臺主機需具有四要素
獲取這四要素分兩種方式
1.靜態獲取
即手動配置
2.動態獲取
經過dhcp獲取
以太網頭 | ip頭 | udp頭 | dhcp數據包 |
---|---|---|---|
(1)最前面的」以太網標頭」,設置發出方(本機)的MAC地址和接收方(DHCP服務器)的MAC地址。前者就是本機網卡的MAC地址,後者這時不知道,就填入一個廣播地址:FF-FF-FF-FF-FF-FF。
(2)後面的」IP標頭」,設置發出方的IP地址和接收方的IP地址。這時,對於這二者,本機都不知道。因而,發出方的IP地址就設爲0.0.0.0,接收方的IP地址設爲255.255.255.255。
(3)最後的」UDP標頭」,設置發出方的端口和接收方的端口。這一部分是DHCP協議規定好的,發出方是68端口,接收方是67端口。
這個數據包構造完成後,就能夠發出了。以太網是廣播發送,同一個子網絡的每臺計算機都收到了這個包。由於接收方的MAC地址是FF-FF-FF-FF-FF-FF,看不出是發給誰的,因此每臺收到這個包的計算機,還必須分析這個包的IP地址,才能肯定是否是發給本身的。當看到發出方IP地址是0.0.0.0,接收方是255.255.255.255,因而DHCP服務器知道」這個包是發給個人」,而其餘計算機就能夠丟棄這個包。
接下來,DHCP服務器讀出這個包的數據內容,分配好IP地址,發送回去一個」DHCP響應」數據包。這個響應包的結構也是相似的,以太網標頭的MAC地址是雙方的網卡地址,IP標頭的IP地址是DHCP服務器的IP地址(發出方)和255.255.255.255(接收方),UDP標頭的端口是67(發出方)和68(接收方),分配給請求端的IP地址和本網絡的具體參數則包含在Data部分。
新加入的計算機收到這個響應包,因而就知道了本身的IP地址、子網掩碼、網關地址、DNS服務器等等參數
本機獲取
4.2 打開瀏覽器,訪問
想要訪問Google,在地址欄輸入了網址:www.google.com。
dns協議(基於udp協議)
13臺根dns:
A.root-servers.net198.41.0.4美國
B.root-servers.net192.228.79.201美國(另支持IPv6)
C.root-servers.net192.33.4.12法國
D.root-servers.net128.8.10.90美國
E.root-servers.net192.203.230.10美國
F.root-servers.net192.5.5.241美國(另支持IPv6)
G.root-servers.net192.112.36.4美國
H.root-servers.net128.63.2.53美國(另支持IPv6)
I.root-servers.net192.36.148.17瑞典
J.root-servers.net192.58.128.30美國
K.root-servers.net193.0.14.129英國(另支持IPv6)
L.root-servers.net198.32.64.12美國
M.root-servers.net202.12.27.33日本(另支持IPv6)
域名定義:http://jingyan.baidu.com/article/1974b289a649daf4b1f774cb.html
頂級域名:以.com,.net,.org,.cn等等屬於國際頂級域名,根據目前的國際互聯網域名體系,國際頂級域名分爲兩類:類別頂級域名(gTLD)和地理頂級域名(ccTLD)兩種。類別頂級域名是 以"COM"、"NET"、"ORG"、"BIZ"、"INFO"等結尾的域名,均由國外公司負責管理。地理頂級域名是以國家或地區代碼爲結尾的域名,如"CN"表明中國,"UK"表明英國。地理頂級域名通常由各個國家或地區負責管理。
二級域名:二級域名是以頂級域名爲基礎的地理域名,比喻中國的二級域有,.com.cn,.net.cn,.org.cn,.gd.cn等.子域名是其父域名的子域名,比喻父域名是abc.com,子域名就是www.abc.com或者.abc.com.
通常來講,二級域名是域名的一條記錄,好比alidiedie.com是一個域名,www.alidiedie.com是其中比較經常使用的記錄,通常默認是用這個,可是相似.alidiedie.com的域名所有稱做是alidiedie.com的二級
看socket以前,先來回顧一下五層通信流程:
但實際上從傳輸層開始以及如下,都是操做系統幫我們完成的,下面的各類包頭封裝的過程,用我們去一個一個作麼?NO!
Socket又稱爲套接字,它是應用層與TCP/IP協議族通訊的中間軟件抽象層,它是一組接口。在設計模式中,Socket其實就是一個門面模式,它把複雜的TCP/IP協議族隱藏在Socket接口後面,對用戶來講,一組簡單的接口就是所有,讓Socket去組織數據,以符合指定的協議。當咱們使用不一樣的協議進行通訊時就得使用不一樣的接口,還得處理不一樣協議的各類細節,這就增長了開發的難度,軟件也不易於擴展(就像咱們開發一套公司管理系統同樣,報帳、會議預約、請假等功能不須要單獨寫系統,而是一個系統上多個功能接口,不須要知道每一個功能如何去實現的)。因而UNIX BSD就發明了socket這種東西,socket屏蔽了各個協議的通訊細節,使得程序員無需關注協議自己,直接使用socket提供的接口來進行互聯的不一樣主機間的進程的通訊。這就比如操做系統給咱們提供了使用底層硬件功能的系統調用,經過系統調用咱們能夠方便的使用磁盤(文件操做),使用內存,而無需本身去進行磁盤讀寫,內存管理。socket其實也是同樣的東西,就是提供了tcp/ip協議的抽象,對外提供了一套接口,同過這個接口就能夠統1、方便的使用tcp/ip協議的功能了。
其實站在你的角度上看,socket就是一個模塊。咱們經過調用模塊中已經實現的方法創建兩個進程之間的鏈接和通訊。也有人將socket說成ip+port,由於ip是用來標識互聯網中的一臺主機的位置,而port是用來標識這臺機器上的一個應用程序。 因此咱們只要確立了ip和port就能找到一個應用程序,而且使用socket模塊來與之通訊。
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,而後與端口綁定(bind),對端口進行監聽(listen),調用accept阻塞,等待客戶端鏈接。在這時若是有個客戶端初始化一個Socket,而後鏈接服務器(connect),若是鏈接成功,這時客戶端與服務器端的鏈接就創建了。客戶端發送數據請求,服務器端接收請求並處理請求,而後把迴應數據發送給客戶端,客戶端讀取數據,最後關閉鏈接,一次交互結束
package main import ( "fmt" "net" ) func main() { // 監聽 listener,err := net.Listen("tcp","127.0.0.1:8000") if err != nil{ fmt.Println("err =",err) return } defer listener.Close() // 阻塞等待用戶連接 conn,err := listener.Accept() if err != nil { fmt.Println("err =",err) return } // 接受用戶的請求 buf := make([]byte,1024) // 緩衝區大小1024 conn.Read(buf) n , err1 := conn.Read(buf) if err1 != nil { fmt.Println("err1=",err1) return } fmt.Println("buf=",string(buf[:n])) defer conn.Close() } // 可使用nc代替客戶端發信息
package main import ( "fmt" "net" ) func main() { // 自動連接服務器 conn,err := net.Dial("tcp","127.0.0.1:8000") if err != nil{ fmt.Println("err:=",err) return } defer conn.Close() // 發送數據 conn.Write([]byte("youmen")) }
// Server.go package main import ( "fmt" "net" "strings" ) func main() { // 監聽 listener,err := net.Listen("tcp","127.0.0.1:8000") if err != nil{ fmt.Println("err =",err) return } defer listener.Close() // 阻塞等待用戶連接 for { conn, err := listener.Accept() if err != nil { fmt.Println("err =", err) return } // 處理用戶請求,新建一個協程 go HandleConn(conn) } } // 處理用戶請求 func HandleConn(conn net.Conn){ // 函數調用自動關閉 defer conn.Close() // 獲取客戶端的網絡地址信息 addr := conn.RemoteAddr().String() fmt.Println(addr,"add connect success") buf := make([]byte,2048) for { // 讀取用戶數據 n, err := conn.Read(buf) if err != nil { fmt.Println("err = ", err) return } fmt.Printf("[%s]: %s\n",addr, string(buf[:n])) if "exit" == string(buf[:n-1]){ fmt.Println(addr,"exit") return } // 將數據轉換爲大寫,再給用戶數據 conn.Write([]byte(strings.ToUpper(string(buf[:n])))) } } // client.go