1. 深入Python中的網(wǎng)絡(luò)通信

        共 1009字,需瀏覽 3分鐘

         ·

        2020-12-04 11:09


        TCP/IP

        計(jì)算機(jī)與網(wǎng)絡(luò)設(shè)備兩情侶要談戀愛,相互通信,那么雙方就必須有規(guī)則。基于相同的方法,不同的硬件、操作系統(tǒng)之間的通信,都需要一種規(guī)則。而我們就把這種規(guī)則稱為協(xié)議(protocol)。

        TCP/IP 是互聯(lián)網(wǎng)相關(guān)各類協(xié)議族的總稱。TCP/IP是指TCP和IP這兩種協(xié)議。TCP/IP是在IP協(xié)議的通信過程中,使用到的協(xié)議族的統(tǒng)稱。

        TCP/IP協(xié)議族按層次分別為 應(yīng)用層,傳輸層,網(wǎng)絡(luò)層,數(shù)據(jù)鏈路層,物理層。可以按照不同的模型分4層或者是7層。

        將TCP/IP分為5層,越靠下越接近硬件。

        應(yīng)用層:應(yīng)用程序收到傳輸層的數(shù)據(jù)后,接下來就是要進(jìn)行解讀,解讀必須要先規(guī)定好格式,而應(yīng)用層就是規(guī)定應(yīng)用程序的數(shù)據(jù)格式,主要協(xié)議有HTTP等。

        傳輸層:該層為兩臺(tái)主機(jī)上的應(yīng)用程序提供端到端的通信,傳輸層有兩個(gè)傳輸協(xié)議為TCP(傳輸控制協(xié)議)和UDP(用戶數(shù)據(jù)報(bào)協(xié)議),TCP是一個(gè)可靠的面向連接的協(xié)議,UDP是不可靠或者說無連接的協(xié)議。

        網(wǎng)絡(luò)層:決定如何將數(shù)據(jù)從發(fā)送方到接收方,是建立主機(jī)到主機(jī)的通信。

        數(shù)據(jù)鏈路層:控制網(wǎng)絡(luò)層與物理層之間的通信,主要功能是保證物理線路上進(jìn)行可靠的數(shù)據(jù)傳遞。

        物理層:該層負(fù)責(zé)物理傳輸,與鏈路有關(guān),也與傳輸?shù)慕橘|(zhì)有關(guān)。

        客戶端和服務(wù)器具體的

        HTTP

        圖片出自《圖解HTTP》書籍

        三次握手,四次揮手

        TCP三次握手,四次揮手,Runsen也不會(huì)怎么說,就把網(wǎng)上最通俗的圖放在下面 了,還是別看我很牛逼,牛逼的是做圖的大佬。

        三次握手

        四次揮手

        圖片出自公眾號(hào)(程序員小小溪),更多的名詞和概念查找參考公眾號(hào)程序員小小溪的文章~[1]

        Socket

        網(wǎng)絡(luò)編程有一個(gè)重要的概念 socket(套接字),應(yīng)用程序可以通過它發(fā)送或接收數(shù)據(jù),套接字允許應(yīng)用程序?qū)?I/O 插入到網(wǎng)絡(luò)中,并與網(wǎng)絡(luò)中的其他應(yīng)用程序進(jìn)行通信。

        我是來偷窺Python中的網(wǎng)絡(luò)通信Socket,不小心偷窺到了一個(gè)非常不錯(cuò)的Socket好圖

        將上面的圖片整理步驟

        1.建立連接:

        • 服務(wù)器:socket--->address--->bind--->listen--->accept

        • 客戶端:socket--->connect

        2.通信:收一發(fā):recv(1024)<---send(byte)/sendall(byte)

        3.關(guān)閉連接:close()

        實(shí)現(xiàn)簡單的通訊程序

        服務(wù)端,server.py

        #導(dǎo)入socket模塊
        import?socket
        #創(chuàng)建套接字?或使用server?=?socket.socket()
        server?=?socket.socket(socket.AF_INET,?socket.SOCK_STREAM)
        #定義綁定的ip和端口,用元組定義
        ip_port?=?('127.0.0.1',?8888)
        #綁定監(jiān)聽:bind(address),在AF_INET下,以元組(ip,port)的形式表示地址
        server.bind(ip_port)
        #設(shè)置最大連接數(shù),默認(rèn)為1
        server.listen(5)
        #不斷接受連接:one?by?one
        while?True:
        ????print("等待數(shù)據(jù)連接中……")
        ????#接受客服端數(shù)據(jù)請求
        ????conn,?address?=?server.accept()
        ????'''
        ????向客服端返回信息
        ????(注意:python3.x以上,網(wǎng)絡(luò)數(shù)據(jù)的發(fā)送接收都是byte類型,
        ????發(fā)送接收String類型數(shù)據(jù)時(shí)需要對數(shù)據(jù)進(jìn)行編碼(發(fā)送:messages.enconde();接收后轉(zhuǎn)為String類型:messages.deconde())pyhon2.x則直接發(fā)送數(shù)據(jù)無須編碼)
        ????'''
        ????messages?=?"連接成功!"
        ????conn.send(messages.encode())
        ????#計(jì)數(shù)信息條數(shù)
        ????count?=?0
        ????#一個(gè)連接中,不斷的接受客戶端發(fā)來的數(shù)據(jù)
        ????while?True:
        ????????data?=?conn.recv(1024)
        ????????#打印客戶端發(fā)來的數(shù)據(jù)信息
        ????????print(data.decode())
        ????????#判斷是否退出當(dāng)前連接,等在下一個(gè)連接
        ????????if?data?==?b'exit':
        ??????????break
        ????????#處理客戶端數(shù)據(jù)(如:響應(yīng)請求等)
        ????????count?=?count?+?1
        ????????string?=?"第"?+?str(count)?+?"條信息:"?+?data.decode()
        ????????conn.send(string.encode())
        ????????#主動(dòng)關(guān)閉連接
        ????conn.close()

        客戶端,client.py

        import?socket

        #創(chuàng)建套接字
        client?=?socket.socket()
        #訪問的服務(wù)器的ip和端口,用元組定義
        ip_port?=?("127.0.0.1",?8888)
        #連接服務(wù)器主機(jī)
        client.connect(ip_port)
        #同一鏈接中,不斷向服務(wù)器發(fā)生數(shù)據(jù)或請求
        while?True:
        ????#接收服務(wù)器發(fā)送或響應(yīng)的數(shù)據(jù)
        ????data?=?client.recv(1024)
        ????#打印接收的數(shù)據(jù);python3.x以上數(shù)據(jù)要編碼(發(fā)送:data.enconde();接收后轉(zhuǎn)為String類型:data.deconde())
        ????print(data.decode())
        ????messages?=?input("請輸入發(fā)生或請求的數(shù)據(jù)(exit退出):")
        ????client.send(messages.encode())
        ????if?messages?==?'exit':
        ????????break
        ????'''
        ????#接收服務(wù)器發(fā)送或響應(yīng)的數(shù)據(jù)
        ????data?=?client.recv(1024)
        ????#打印接收的數(shù)據(jù);python3.x以上數(shù)據(jù)要編碼,發(fā)送enconde();接收deconde()
        ????print(data.decode())
        ????'''
        #關(guān)閉連接
        client.close()

        具體效果如下圖所示。

        多線程通信

        TCP服務(wù)器與多個(gè)TCP客戶端同時(shí)進(jìn)行連續(xù)通信,只需要通過threading創(chuàng)建多線程任務(wù)handle_client就可以了。

        import?socket
        import?threading
        import?random


        def?handle_client():
        ????#?接受客戶端請求鏈接
        ????client,?address?=?server.accept()
        ????print("[*]?Accept?connection?from:?%s:%d"?%?(address[0],?address[1]))
        ????messages?=?"Hello?World!"
        ????client.send(messages.encode())
        ????#?連續(xù)與當(dāng)前連接的客戶端通信
        ????while?True:
        ????????#?接受客戶端數(shù)據(jù)
        ????????request?=?(client.recv(1024)).decode()
        ????????#?判斷是否結(jié)束通信
        ????????if?request?==?'exit':
        ????????????break
        ????????print("[*]?Received?from?%s:%d?:?%s"?%?(address[0],?address[1],?request))
        ????????#?發(fā)送響應(yīng)信息給客戶端
        ????????client.send((str(random.randint(1, 1000))?+?":"?+?"ACK!").encode())
        ????#?關(guān)閉當(dāng)前連接
        ????client.close()


        if?__name__?==?"__main__":
        ????#?創(chuàng)建套接字
        ????server?=?socket.socket(socket.AF_INET,?socket.SOCK_STREAM)
        ????#?定義綁定ip和端口
        ????ip?=?'127.0.0.1'
        ????port?=?8888
        ????#?綁定監(jiān)聽
        ????server.bind((ip,?port))
        ????#?設(shè)置最大連接數(shù),默認(rèn)為1
        ????server.listen(5)
        ????print("[*]?Listening?on?%s:%d"?%?(ip,?port))
        ????#?循環(huán)開啟線程,接受多個(gè)客戶端的鏈接通信
        ????while?True:
        ????????#?創(chuàng)建一個(gè)線程
        ????????client_handler?=?threading.Thread(target=handle_client)
        ????????#?開啟線程
        ????????client_handler.start()

        python3.x以上,網(wǎng)絡(luò)數(shù)據(jù)messages的發(fā)送接收都是byte類型,若要發(fā)送接收String類型數(shù)據(jù)時(shí)需要通過messages.enconde()對數(shù)據(jù)進(jìn)行編碼,接收后通過messages.deconde()轉(zhuǎn)為String類型。pyhon2.x則直接發(fā)送數(shù)據(jù)無須編碼。

        ?

        本文已收錄 GitHub,傳送門~[2] ,里面更有大廠面試完整考點(diǎn),歡迎 Star。

        ?


        Reference

        [1]

        參考公眾號(hào)程序員小小溪的文章: https://mp.weixin.qq.com/s/KK1dnNoHrbjMyuhQptaBAQ

        [2]

        傳送門~: https://github.com/MaoliRUNsen/runsenlearnpy100

        - END -

        推薦閱讀:
        Pandas數(shù)據(jù)可視化原來也這么厲害
        畫圖神器pyecharts-旭日圖
        刷爆網(wǎng)絡(luò)的動(dòng)態(tài)條形圖,3行Python代碼就能搞定
        Python中讀取圖片的6種方式
        2020年11月國內(nèi)大數(shù)據(jù)競賽信息-獎(jiǎng)池5000萬
        Python字典詳解-超級(jí)完整版
        刷爆網(wǎng)絡(luò)的動(dòng)態(tài)條形圖,3行Python代碼就能搞定
        一個(gè)有意思還有用的Python包-漢字轉(zhuǎn)換拼音


        學(xué)習(xí)交流群

        ↓內(nèi)推、交流加小編

        掃描二維碼關(guān)注本號(hào)↓


        瀏覽 24
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
          
          

            1. 天堂va欧美ⅴa亚洲va一夜 | 国产一级a毛一a毛免费视频 | 超碰影院在线观看 | 天天草比网 | 乌克兰bbox |