通信簡(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)頁,可以使用清除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)槎丝诓灰粯?,也能保證信息發(fā)送給正確的人。端口號(hào)的范圍從0到65535 (2^16-1),比如用于瀏覽網(wǎng)頁服務(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

















