參考于:python cs架構(gòu)實(shí)現(xiàn)簡單文件傳輸
原文中程序運(yùn)行有誤螟左,在此做修改與解釋,如下:
功能說明:
共2個(gè)py文件分別為server和client端巷嚣,采用socket進(jìn)行通信涂籽。提供兩種功能:“dir“ 命令用于顯示服務(wù)器端可下載文件名评雌;“get/put+文件名“ 命令用于與服務(wù)器端進(jìn)行下載或發(fā)送數(shù)據(jù)交換直焙。?
服務(wù)器上socket編寫步驟:
1.調(diào)用socket函數(shù)創(chuàng)建socket對(duì)象奔誓,如:
socket_server = socket.socket(family,type)
family參數(shù)代表地址家族厨喂,可為AF_INET(Internet通信)或AF_UNIX(同一臺(tái)機(jī)器上進(jìn)程間通信)蜕煌。
type參數(shù)代表套接字類型,可為SOCK_STREAM(流套接字)和SOCK_DGRAM(數(shù)據(jù)報(bào)套接字)贫母。
2.使用socket對(duì)象的bind方法腺劣,將socket綁定到指定地址橘原,如:
socket_server.bind(address)
由AF_INET所創(chuàng)建的套接字贮聂,address必須是一組雙元素元組吓懈,格式為(host,port)隔嫡。
3.使用socket對(duì)象的listen方法接受連接請(qǐng)求腮恩,如:
socket_server.listen(backlog)
backlog指定最多允許多少個(gè)客戶連接到服務(wù)器秸滴,至少為1,如果達(dá)到設(shè)定值咒唆,則拒絕接受新請(qǐng)求全释。
4.服務(wù)器套接字通過socket對(duì)象的accept方法等待客戶請(qǐng)求一個(gè)連接误债,如:
connection寝蹈,address = socket_server.accept()
運(yùn)行accept方法后箫老,socket進(jìn)入“waiting”狀態(tài)槽惫,等待客戶請(qǐng)求連接辩撑。當(dāng)客戶請(qǐng)求連接時(shí)合冀,accept方法建立連接并返回服務(wù)器君躺,返回一組含兩個(gè)元素的元組(connection,address)林螃。connection是新的socket對(duì)象疗认,服務(wù)器必須通過這個(gè)新的對(duì)象與客戶端進(jìn)行通信横漏;address是客戶端的Internet地址。
5.處理階段扎拣,服務(wù)器和客戶端通過“send”和“recv”方法通信:
服務(wù)器調(diào)用send二蓝,并采用?二進(jìn)制??形式向客戶發(fā)送信息侣夷。send方法返回已發(fā)送的字符個(gè)數(shù)仑乌。
服務(wù)器使用recv方法從客戶端接受信息,調(diào)用recv時(shí)衙传,服務(wù)器必須指定一個(gè)整數(shù)來表示可通過本次方法調(diào)用來接受的最大數(shù)據(jù)量蓖捶。recv方法在接收數(shù)據(jù)時(shí)會(huì)進(jìn)入“blocked”狀態(tài)俊鱼,最后返回一個(gè)字符串畅买,它表示收到的數(shù)據(jù)谷羞。如果發(fā)送數(shù)據(jù)量超過recv所允許湃缎,數(shù)據(jù)會(huì)被截?cái)嗌のァ6嘤嗟臄?shù)據(jù)將緩沖到接收端靠瞎。以后調(diào)用recv時(shí)求妹,多余的數(shù)據(jù)會(huì)從緩沖區(qū)刪除制恍。
6.傳輸結(jié)束净神,調(diào)用socket對(duì)象的close方法關(guān)閉連接鹃唯,如:
connection.close()
socket_server.close()
注意:這里先關(guān)閉accept創(chuàng)建的新socket(connection)然后關(guān)閉服務(wù)器端socket(socket_server)
客戶端上socket編寫步驟:
1.創(chuàng)建一個(gè)socket以連接服務(wù)器坡慌,如:
socket_client = socket.socket(family,type)
2.使用connect方法連接服務(wù)器藻三,對(duì)于AF_INET而言鏈接格式如:
socket_client.connect((host,port))
host代表主服務(wù)器主機(jī)名或IP棵帽,port為服務(wù)器進(jìn)程所綁定的端口號(hào)逗概。
3.處理階段逾苫,客戶端和服務(wù)器端通過send與recv方法進(jìn)行通信
4.傳輸結(jié)束铅搓,調(diào)用close方法關(guān)閉連接狸吞,如:
socket_client.close()
注意這里的socket_client是第一步創(chuàng)建的對(duì)象指煎,而服務(wù)器端使用的是accept創(chuàng)建的新socket(connection)
關(guān)于TCP的三次握手建立連接和四次揮手?jǐn)嚅_連接這里不做敘述(徹底講解我功夫不到家至壤,不敢亂說)像街,把圖轉(zhuǎn)來大家看一下(這個(gè)感覺很基礎(chǔ), 但很重要):
程序如下:
服務(wù)器端:
客戶端:
運(yùn)行說明:
1.首先建立server.py和client.py文件重绷,并分別置于兩個(gè)不同的位置沸停,如圖:
在Server文件夾下放一個(gè)或多個(gè)文件用于下載(我這里是4個(gè)不同類型的文件以供下文dir指令調(diào)用)
在Client文件下放一個(gè)或多個(gè)文件用于上傳(我這里是一個(gè)word文本)
2.在Server目錄下運(yùn)行server.py,等待客戶端發(fā)送連接請(qǐng)求:
3.在Client目錄下運(yùn)行client.py昭卓,向服務(wù)器端發(fā)送連接請(qǐng)求:
注意:先啟動(dòng)服務(wù)器愤钾,再啟動(dòng)客戶端,這個(gè)為什么不用多說吧葬凳?
4.在客戶端輸入“dir”指令,查看可下載目錄文件:
注:這里我用“\t“即制表符來控制顯示格式火焰,但不知道為啥第一個(gè)文件后會(huì)自動(dòng)換行劲装,暫且放著不去管它(不影響通信功能)
5.在客戶端輸入“get”指令,下載服務(wù)器中指定文件:
6.在客戶端輸入“put”指令昌简,上傳指定文件到服務(wù)器:
7.在客戶端輸入“close”指令占业,關(guān)閉連接,服務(wù)器進(jìn)入監(jiān)聽狀態(tài):
注意幾點(diǎn):
1.send方法的第一個(gè)參數(shù)是二進(jìn)制數(shù)據(jù)纯赎,使用bytes(字符串谦疾,encoding='utf-8')將字符串改為二進(jìn)制進(jìn)行發(fā)送
2.在做指令判斷的時(shí)候,需要將“get”犬金、“put”等指令轉(zhuǎn)為二進(jìn)制念恍,才能與接收到的指令進(jìn)行判斷,這里不將二進(jìn)制轉(zhuǎn)為字符串(這樣易于理解)的原因是晚顷,我沒找到一個(gè)簡單的方法讓二進(jìn)制轉(zhuǎn)str(我不會(huì))
3.理清楚創(chuàng)建流程后峰伙,主要的困難就是轉(zhuǎn)換數(shù)據(jù)格式,哪里需要轉(zhuǎn)哪里不需要该默,自己寫一遍瞳氓,再debug一會(huì)兒就會(huì)弄明白了