當(dāng)前位置:
首頁(yè) >
假期(网络编程)
發(fā)布時(shí)間:2025/3/14
28
豆豆
"""
一、客戶(hù)端/服務(wù)端架構(gòu):1、硬件C/S架構(gòu)(打印機(jī))2、軟件C/S架構(gòu)互聯(lián)網(wǎng)中處處都是CS架構(gòu),服務(wù)端與客戶(hù)端CS架構(gòu)與socket的關(guān)系- 我們學(xué)習(xí)socket就是為了完成C/S架構(gòu)的開(kāi)發(fā)二、OSI七層模型:一個(gè)完整的計(jì)算機(jī)系統(tǒng)是由硬件、操作系統(tǒng)、應(yīng)用軟件三者組成,一臺(tái)計(jì)算機(jī)只能自己玩自己,要想跟別人玩就需要上網(wǎng)了互聯(lián)網(wǎng)的核心就是由一堆協(xié)議組成,協(xié)議就是標(biāo)準(zhǔn),比如全世界人通信的標(biāo)準(zhǔn)是英語(yǔ);如果把計(jì)算機(jī)比做人,那么互聯(lián)網(wǎng)協(xié)議就是計(jì)算機(jī)界的英語(yǔ)了,如果所有的計(jì)算機(jī)都學(xué)會(huì)了這門(mén)英語(yǔ),那么就可以互相通信了為何學(xué)習(xí)socket一定要先學(xué)習(xí)互聯(lián)網(wǎng)協(xié)議:- 1、首先我們的目標(biāo)是基于socket編程,來(lái)開(kāi)發(fā)一款自己的cs架構(gòu)軟件- 2、其次cs架構(gòu)軟件(軟件屬于應(yīng)用層)是基于網(wǎng)絡(luò)進(jìn)行通信的- 3、網(wǎng)絡(luò)的核心即一堆協(xié)議,協(xié)議即標(biāo)準(zhǔn),你想開(kāi)發(fā)一款基于網(wǎng)絡(luò)通信的軟件,就必須遵循這些標(biāo)準(zhǔn)三、socket層socket層位于運(yùn)輸層和應(yīng)用層之間,即socket抽象層四、socket是什么?socket是應(yīng)用層與TCP/IP協(xié)議族通信的中間軟件抽象層,它是一組接口。在設(shè)計(jì)模式中,socket其實(shí)就是一個(gè)門(mén)面模式,它吧復(fù)雜的TCP/IP協(xié)議族隱藏在了socket接口的后面,對(duì)用戶(hù)來(lái)說(shuō),一組簡(jiǎn)單的接口就是全部,讓socket去組織數(shù)據(jù),以符合指定的協(xié)議所以我們無(wú)需深入理解tcp/udp協(xié)議,socket已經(jīng)幫我們封裝好了,我們只需要遵循socket的規(guī)定去編程,寫(xiě)出的程序自然符合標(biāo)準(zhǔn)- 也有人將socket說(shuō)成是IP+port,IP是用來(lái)標(biāo)識(shí)互聯(lián)網(wǎng)中的一臺(tái)主機(jī)的位置,而port是用來(lái)標(biāo)識(shí)這臺(tái)主機(jī)上的一個(gè)應(yīng)用程序,IP地址配置到網(wǎng)卡上的,而port是應(yīng)用程序開(kāi)啟的,IP與port的綁定就標(biāo)識(shí)了互聯(lián)網(wǎng)中獨(dú)一無(wú)二的應(yīng)用程序程序的pid是同一臺(tái)機(jī)器上不同進(jìn)程或者線程的標(biāo)識(shí)五、套接字的分類(lèi):- 基于文件類(lèi)型的套接字家族套接字家族的名字:AF_UNIXunix一切皆文件,基于文件的套接字調(diào)用的就是底層文件系統(tǒng)來(lái)取數(shù)據(jù),兩個(gè)套接字進(jìn)程運(yùn)行在同一機(jī)器,可以通過(guò)訪問(wèn)同一個(gè)間接完成通信。- 基于網(wǎng)絡(luò)類(lèi)型的套接字家族套接字家族的名字:AF_INET···所有的地址家族中,AF_INET是使用最廣泛的一個(gè),python支持很多種地址家族,但是由于我們只關(guān)心網(wǎng)絡(luò)編程,所以我們大部分時(shí)間都只是使用AF_INET六、套接字的工作流程:一個(gè)生活中的場(chǎng)景:你要給你前對(duì)象打電話(huà),先撥號(hào),前對(duì)象聽(tīng)到電話(huà)鈴聲后拿起電話(huà),這時(shí)候你倆就建立起來(lái)了不正當(dāng)?shù)逆溄?#xff0c;然后就可以進(jìn)行不正當(dāng)?shù)慕灰琢恕=灰淄瓿珊?#xff0c;掛斷電話(huà)結(jié)束此次交談;先從服務(wù)端說(shuō)起,服務(wù)端先初始化socket,然后與端口綁定(bind),對(duì)端口進(jìn)行監(jiān)聽(tīng)(listen),調(diào)用accept阻塞,等待客戶(hù)端鏈接在這個(gè)時(shí)候如果有客戶(hù)端初始化一個(gè)socket,然后鏈接服務(wù)器(connect),如果鏈接成功,這時(shí)客戶(hù)端與服務(wù)端的鏈接就建立了。客戶(hù)端發(fā)送數(shù)據(jù)請(qǐng)求,服務(wù)端接收請(qǐng)求并處理,然后把回應(yīng)數(shù)據(jù)發(fā)送給客戶(hù)端,客戶(hù)端讀取數(shù)據(jù),關(guān)閉鏈接,交互結(jié)束- socket函數(shù)的用法import socketsocket.socket(socket_family,socket_type,protocal=0)socket_family:可以是AF_UNIX或者是AF_INET;socket_type可以是SOCK_STREAM或SOCK_DGRAM,protocol一般默認(rèn)為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 * 的語(yǔ)句導(dǎo)入,這樣就可以減少代碼量eg:tcpsock = socket(AF_INET,SOCK_STREAM)- 服務(wù)端套接字函數(shù)s.bind()綁定(主機(jī),端口號(hào))到套接字s.listen()開(kāi)始tcp監(jiān)聽(tīng)s.accept()被動(dòng)接受tcp客戶(hù)的連接,(阻塞式)等待連接的到來(lái)- 客戶(hù)端套接字函數(shù)c.connect()被動(dòng)初始化tcp服務(wù)器連接c.connect_ex() connect()函數(shù)的擴(kuò)展版本,出錯(cuò)時(shí)返回錯(cuò)誤碼,而不是拋出異常- 公共用途的套接字函數(shù)s.recv()接受tcp數(shù)據(jù)s.send()發(fā)送tcp數(shù)據(jù)(send在待發(fā)送數(shù)據(jù)量大于已緩存區(qū)剩余的空間時(shí),數(shù)據(jù)丟失,不會(huì)發(fā)完)s.sendall()發(fā)送完整的tcp數(shù)據(jù)(本質(zhì)就是循環(huán)send,···數(shù)據(jù)不會(huì)丟失)s.recvfrom()接受udp數(shù)據(jù)s.sendto()發(fā)送udp數(shù)據(jù)s.getpeername()鏈接到當(dāng)前套接字的遠(yuǎn)程地址s.getsockname()當(dāng)前套接字的地址s.getsockopt()返回指定套接字的參數(shù)s.setsockopt()設(shè)置指定套接字的參數(shù)s.close()關(guān)閉套接字鏈接- 面向鎖的套接字方法s.setblocking()設(shè)置套接字的阻塞與非阻塞模式s.settimeout()設(shè)置阻塞套接字操作的超時(shí)時(shí)間s.gettimeout()得到阻塞套接字操作的超時(shí)時(shí)間- 面向文件的套接字函數(shù)s.fileno()套接字的文件描述符s.makefile()創(chuàng)建一個(gè)與該套接字相關(guān)的文件
七、基于tcp的套接字tcp是基于鏈接的,必須先啟動(dòng)服務(wù)端,然后再啟動(dòng)客戶(hù)端去鏈接服務(wù)端- tcp服務(wù)端:server = socket() #創(chuàng)建服務(wù)器套接字server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)server.bind() #把地址綁定到套接字server.listen() #監(jiān)聽(tīng)鏈接while true: #服務(wù)器無(wú)限循環(huán)client,addr = server.accept() #接受客戶(hù)端鏈接while True: #通信循環(huán)client.recv()/client.send() #接收與發(fā)送數(shù)據(jù)client.close() #關(guān)閉客戶(hù)端套接字server.close() #關(guān)閉服務(wù)器套接字- tcp客戶(hù)端:client = socket() #創(chuàng)建客戶(hù)端套接字client.connect() #嘗試鏈接服務(wù)器while True:client.send()/client.recv() #發(fā)送/接收數(shù)據(jù)client.close() #關(guān)閉客戶(hù)端套接字八、基于udp的套接字- udp服務(wù)端server = socket() #創(chuàng)建服務(wù)器套接字server.bind() #綁定套接字地址while True: #服務(wù)器無(wú)線循環(huán)client,addr = server.recvfrom()/server.sendto() #接收與發(fā)送數(shù)據(jù)server.close() #關(guān)閉服務(wù)器套接字- udp客戶(hù)端client = socket() #創(chuàng)建客戶(hù)端套接字while True: #通信循環(huán)client.sendto()/client.recvfrom() #發(fā)送與接收數(shù)據(jù)client.close() #關(guān)閉客戶(hù)端套接字九、粘包現(xiàn)象(了解)如果當(dāng)我們用socket模擬cmd執(zhí)行遠(yuǎn)程命令時(shí),有些數(shù)據(jù)太長(zhǎng),超過(guò)了1024個(gè)字節(jié),一次接受不完,就會(huì)造成粘包- 什么是粘包?只有tcp才有粘包現(xiàn)象,udp永遠(yuǎn)不會(huì)粘包,因?yàn)閡dp是基于流收發(fā)數(shù)據(jù)的所謂粘包的問(wèn)題主要還是因?yàn)榻邮辗讲恢老⒅g的界限,不知道一次性提取多少數(shù)據(jù)造成的- 粘包的解決- struct模塊- 自定義報(bào)頭- ···- 什么時(shí)候才會(huì)發(fā)生粘包?發(fā)送端需要等緩沖區(qū)滿(mǎn)才發(fā)送出去,造成粘包(發(fā)送數(shù)據(jù)時(shí)間間隔很短,數(shù)據(jù)很小會(huì)喝到一起,產(chǎn)生粘包)接收方不及時(shí)接收緩沖區(qū)的包,造成多個(gè)包接收產(chǎn)生粘包- 了解tcp是可靠傳輸,udp是不可靠傳輸十、socketserver模塊- 終極必殺技"""
?
轉(zhuǎn)載于:https://www.cnblogs.com/52-qq/p/8449470.html
總結(jié)
- 上一篇: Kafka学习之(五)搭建kafka集群
- 下一篇: wannalfy 挑战赛8 F 白云的