通信簡(jiǎn)單來說指的就是信息的傳遞达椰。官方一點(diǎn)的話,人與人街夭,或人與自然之間砰碴,通過某種行為或媒介,進(jìn)行的信息交流與傳遞板丽,叫做通信呈枉。身處信息時(shí)代的我們,對(duì)通信的需求和依賴變得前所未有的強(qiáng)烈埃碱,所以掌握最基本的通信原理知識(shí)是我們每個(gè)人都應(yīng)該做的猖辫。
下文寫的傳輸模型和TCP協(xié)議,對(duì)大家了解最基本的通信原理知識(shí)很有幫助砚殿,所以不妨花點(diǎn)時(shí)間看一看啃憎。
1. 傳輸模型
1.1. 基本認(rèn)知
1.2 層次模型
各層說明
1.2.1 應(yīng)用層
有網(wǎng)卻無法登錄網(wǎng)頁(yè),可以使用清除DNS緩存的方式似炎。
1.2.2. 傳輸層
網(wǎng)絡(luò)協(xié)議是指通信雙方就通信如何進(jìn)行所必須共同遵守的約定和通信規(guī)則的集合辛萍。在網(wǎng)絡(luò)上通信的雙方只有遵守相同的協(xié)議,才能正確地交流信息羡藐。
1.2.2.1. TCP
- 通過三次握手協(xié)議建立穩(wěn)定鏈接
2.應(yīng)用數(shù)據(jù)分割成最合適的數(shù)據(jù)塊發(fā)送
3.鏈接可靠贩毕,不易出現(xiàn)亂序、丟失等現(xiàn)象
4.連接和檢驗(yàn)等都需要花不少時(shí)間仆嗦,效率因此會(huì)降低
1.2.2.2. UDP
1.一次性發(fā)送所有數(shù)據(jù)辉阶,無需建立連接
2.服務(wù)器可以同時(shí)發(fā)送給多個(gè)客戶機(jī)
3.沒有檢驗(yàn),容易會(huì)出現(xiàn)信息丟失
4.消耗資源小瘩扼,處理速度快
1.2.2.3. 端口
當(dāng)同時(shí)多個(gè)程序使用網(wǎng)絡(luò)時(shí)谆甜,為了保證信息發(fā)送到正確的地方,增加了端口集绰,不同的軟件使用不同的端口规辱,雖然使用同一個(gè)網(wǎng)絡(luò),但是因?yàn)槎丝诓灰粯釉匝啵材鼙WC信息發(fā)送給正確的人按摘。端口號(hào)的范圍從0到65535 (2^16-1),比如用于瀏覽網(wǎng)頁(yè)服務(wù)的80端口纫谅,用于FTP服務(wù)的21端口等。ip地址用于區(qū)分不同的主機(jī)溅固,而端口號(hào)是用于區(qū)分一個(gè)主機(jī)下的不同網(wǎng)絡(luò)服務(wù)付秕。
1.2.3. 網(wǎng)絡(luò)層
1.2.3.1. IPV4和IPV6
ipv4是第一個(gè)被廣泛應(yīng)用的ip,IP是TCP/IP協(xié)議族中網(wǎng)絡(luò)層的協(xié)議侍郭,是TCP/IP協(xié)議族的核心協(xié)議询吴。
ipv4的地址長(zhǎng)度規(guī)定為32位掠河,分為四段,每段8位且以點(diǎn)隔開猛计,并以十進(jìn)制形式表示唠摹,故每段的數(shù)值范圍為0~255,即最小的為0.0.0.0奉瘤,最大為255.255.255.255勾拉。
由于ipv4位數(shù)使得其地址資源己被分配完,故產(chǎn)生了ipv6盗温。
ipv6的長(zhǎng)度是ipv4的四倍藕赞,以十六進(jìn)制形式表示,其被分為8段卖局,每段以冒號(hào)隔開斧蜕。
其中地址塊127.0.0.1被保留作環(huán)回通信用,0.0.0.0為任意使用。
2. TCP協(xié)議
2.1. 三次握手
第一步:客戶端發(fā)送SYN報(bào)文給服務(wù)器端砚偶,進(jìn)入SYN_SEND狀態(tài)批销。
第二步:服務(wù)器端收到SYN報(bào)文,回應(yīng)一個(gè)SYN ACK報(bào)文染坯,進(jìn)入SYN_RECV狀態(tài)均芽。
第三步:客戶端收到服務(wù)器端的SYN報(bào)文,回應(yīng)一個(gè)ACK報(bào)文酒请,進(jìn)入Established狀態(tài)骡技。
【注】先開啟服務(wù)端
三次握手完成,TCP客戶端和服務(wù)器端成功地建立連接羞反,可以開始傳輸數(shù)據(jù)了布朦。過程如下圖所示:
三次握手
2.2. 傳輸數(shù)據(jù)
短連接(類似于打字聊天):
建立連接--數(shù)據(jù)傳輸--關(guān)閉連接...建立連接--數(shù)據(jù)傳輸--關(guān)閉連接
長(zhǎng)連接(類似于語音、視頻通話):
建立連接--數(shù)據(jù)傳輸...(保持連接)...數(shù)據(jù)傳輸--關(guān)閉連接
2.3. 四次揮手
第一步:先由客戶端向服務(wù)器端發(fā)送一個(gè)FIN昼窗,請(qǐng)求關(guān)閉數(shù)據(jù)傳輸是趴。
第二步:當(dāng)服務(wù)器接收到客戶端的FIN時(shí),向客戶端發(fā)送一個(gè)ACK澄惊,其中ack的值等于FIN+SEQ唆途。
第三步:然后服務(wù)器向客戶端發(fā)送一個(gè)FIN,告訴客戶端應(yīng)用程序關(guān)閉掸驱。
第四步:當(dāng)客戶端收到服務(wù)器端的FIN時(shí)肛搬,回復(fù)一個(gè)ACK給服務(wù)器端。其中ack的值等于FIN+SEQ毕贼。
【注】先關(guān)閉客戶端
四次揮手
2.4. 代碼演示
紫紅背景色的為Oracle VM VirtualBox(充當(dāng)服務(wù)端)
黑背景色的為MobaXterm(充當(dāng)客戶端)
import socket
:導(dǎo)入socket模塊温赔。
server = socket.socket()
:創(chuàng)建一個(gè)socket對(duì)象,命名為服務(wù)器鬼癣。
server
:查看變量server陶贼,fd為文件描述符(唯一標(biāo)識(shí)一個(gè)socket)啤贩;AF_INET表示ipv4,AF_INET6表示ipv6拜秧;SOCK_STREAM表示TCP協(xié)議痹屹,SOCK_DGRAM表示UDP協(xié)議;protocol協(xié)議通常是0枉氮,tcp/ip協(xié)議簇志衍;laddr還沒有綁定,所以都是0嘲恍。
server.bind('127.0.0.1',8989)
:綁定端口足画,注意這里填入的是元組。
server.listen(10)
:設(shè)置最大監(jiān)聽數(shù)佃牛,最大連接量淹辞。
import socket
:導(dǎo)入socket模塊。
client = socket.socket()
:創(chuàng)建一個(gè)socket對(duì)象俘侠,命名為客戶端象缀。
client.connect(('127.0.0.1',8989))
:連接服務(wù)器端口,注意這里填入的是元組爷速。
client.send(b'hello')
:客戶端發(fā)送字節(jié)類型數(shù)據(jù)給服務(wù)器央星,返回字節(jié)數(shù)。
result = server.accept()
與客戶端創(chuàng)建對(duì)等套接字惫东。
conn.,address = result
:元組拆包莉给。
address
:客戶端地址。
conn.recv(1024)
:服務(wù)器接收字節(jié)數(shù)據(jù)廉沮,最大接收長(zhǎng)度為1024颓遏。
conn.send(b'ok ok')
:服務(wù)器發(fā)送字節(jié)類型數(shù)據(jù)給客戶端,返回字節(jié)數(shù)滞时。
client.recv(5)
:客戶端接收字節(jié)數(shù)據(jù)叁幢,最大接收長(zhǎng)度為5。
client.send(b'陳宏好帥')
:未編碼成字節(jié)類型數(shù)據(jù)坪稽,無法發(fā)送曼玩,會(huì)報(bào)錯(cuò)。所以需要修改為st = '陳宏好帥'.encode('utf -8')
窒百,然后再client.send(st)
黍判。
服務(wù)器端接收時(shí)需要先接收客戶端編碼的數(shù)據(jù)再解碼,所以先寫成a = conn.recv(1024)
篙梢,然后再a.decode('utf-8')
:
操作完畢以后顷帖,按照下方順序關(guān)閉:
client.close()
:客戶端先關(guān)閉
conn.close()
:服務(wù)端關(guān)閉套接字
server.close()
:服務(wù)端后關(guān)閉
quit()
:即可退出Python命令行模式
文章到這里就結(jié)束了!希望大家能多多支持Python(系列)!六個(gè)月帶大家學(xué)會(huì)Python窟她,私聊我,可以問關(guān)于本文章的問題蔼水!以后每天都會(huì)發(fā)布新的文章震糖,喜歡的點(diǎn)點(diǎn)關(guān)注!一個(gè)陪伴你學(xué)習(xí)Python的新青年趴腋!不管多忙都會(huì)更新下去吊说,一起加油!
Editor:Lonelyroots