1. 程式人生 > >python學習筆記-網路程式設計

python學習筆記-網路程式設計

#=========================網路程式設計=====================
# 網路:
# 網路協議: 一套規則
# 網路模型:
  # 七層模型,ISO
  # 四層模型,TCP/IP

# 每一層都有相應的協議負責交換資訊或者協同工作
# TCP/IP 協議族
# IP地址:負責在網路上唯一定位一個機器
# 埠
    # 範圍: 0#65535
        # 知名埠:0#1023
        # 非知名埠:1024#
        
# TCP/UDP協議
# UDP:非安全的不面向連結的傳輸
    # 安全性差
    # 大小限制64kb
    # 沒有順序
    # 速度快
# TCP
    # 基於連結的通訊
    
#=========================SOCKET程式設計-UDP=========================
    # socket(套接字): 是一個網路通訊的端點, 能實現不同主機的程序通訊,網路大多基於Socket通訊
    # 通過IP+埠定位對方併發送訊息的通訊機制
    # 分為UDP和TCP
    # 客戶端Client: 發起訪問的一方
    # 伺服器端Server:接受訪問的一方
# UDP 程式設計
    # Server端流程
            1. 建立socket,socket是負責具體通訊的一個例項
            2. 繫結,為建立的socket指派固定的埠和ip地址
            3. 接受對方傳送內容
            4. 給對方傳送反饋,此步驟為非必須步驟
    # Client端流程
            1. 建立通訊的socket
            2. 傳送內容到指定伺服器
            3. 接受伺服器給定的反饋內容
    # 伺服器案例:
    '''
    Server端流程
     1. 建立socket,socket是負責具體通訊的一個例項
     2. 繫結,為建立的socket指派固定的埠和ip地址
     3. 接受對方傳送內容
     4. 給對方傳送反饋,此步驟為非必須步驟
    '''

    # socket模組負責socket程式設計
    import socket

    def serverFunc():
        # 1. 建立socket
        # socket.AF_INET:使用ipv4協議族
        # socket.SOCK_DGRAM: 使用UDP通訊
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

        # 2. 繫結ip和port
        # 127.0.0.1: 這個ip地址代表的是機器本身
        # 7852: 隨手指定的埠號
        # 地址是一個tuple型別,(ip, port)
        addr = ("127.0.0.1", 7852 )
        sock.bind( addr )

        # 接受對方訊息
        # 等待方式為死等, 沒有其他可能性
        # recvfrom接受的返回值是一個tuple,前一項表示資料,後一項表示地址
        # 引數的含義是緩衝區大小
        # rst = sock.recvfrom(500)
        data, addr = sock.recvfrom(500)
        
        # 傳送過來的資料是bytes格式,必須通過解碼才能得到str格式內容
        # decode預設引數是utf8
        text = data.decode()
        print(text)

        # 給對方返回的訊息
        rsp = "return massage:get it"

        # 傳送的資料需要編碼成bytes格式
        # 預設是utf8
        data = rsp.encode()
        sock.sendto(data, addr)

    if __name__ == '__main__':
        # 伺服器程式要求永久執行,一般用死迴圈處理
        while 1:
        try:
            serverFunc()
        except Exception as e:
            print(e)
        time.sleep(1)
        
    # 客戶端案例:
   import socket

    '''
    - Client端流程
                1. 建立通訊的socket
                2. 傳送內容到指定伺服器
                3. 接受伺服器給定的反饋內容
    '''

    def clientFunc():

        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        text = "go go !"
        # 傳送的資料必須是bytes格式
        data = text.encode()
        # 傳送
        sock.sendto(data,  ("127.0.0.1", 7852))
        data, addr  = sock.recvfrom(200)
        data = data.decode()
        print(data)
    if __name__ == '__main__':
        clientFunc()

    
#=========================SOCKET程式設計-TCP=========================
    # 面向連結的傳輸,即每次傳輸之前需要先建立一個連結
     # 客戶端和伺服器端兩個程式需要編寫
     # Server端的編寫流程
         1. 建立socket負責具體通訊,這個socket其實只負責接受對方的請求,真正通訊的是連結後從新建立的socket
         2. 繫結埠和地址
         3. 監聽接入的訪問socket
         4. 接受訪問的socket,可以理解接受訪問即建立了一個通訊的連結通路
         5. 接受對方的傳送內容,利用接收到的socket接收內容
         6. 如果有必要,給對方傳送反饋資訊
         7. 關閉連結通路
     # Client端流程
          1. 建立通訊socket
          2. 連結對方,請求跟對方建立通路
          3. 傳送內容到對方伺服器
          4. 接受對方的反饋
          5. 關閉連結通路
  # TCP服務端案例:
  import socket
    def  tcp_srv():
        # 1. 建立socket負責具體通訊,這個socket其實只負責接受對方的請求,真正通訊的是連結後從新建立的socket
        # 需要用到兩個引數
        # AF_INET: 含義同udp一致
        # SOCK_STREAM: 表明是使用的tcp進行通訊
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 2. 繫結埠和地址
        # 此地址資訊是一個元祖型別內容,元祖分兩部分,第一部分為字串,代表ip,第二部分為埠,是一個整數,推薦大於10000
        addr = ("127.0.0.1", 8998)
        sock.bind(addr)
        # 3. 監聽接入的訪問socket
        sock.listen()

        while True:
            # 4. 接受訪問的socket,可以理解接受訪問即建立了一個通訊的連結通路
            # accept返回的元祖第一個元素賦值給skt,第二個賦值給addr
            skt,addr = sock.accept()
            # 5. 接受對方的傳送內容,利用接收到的socket接收內容
            # 500代表接收使用的buffersize
            #msg = skt.receive(500)
            msg = skt.recv(500)
            # 接受到的是bytes格式內容
            # 想得到str格式的,需要進行解碼
            msg = msg.decode()

            rst = "Received msg: {0} from {1}".format(msg, addr)
            print(rst)
            # 6. 如果有必要,給對方傳送反饋資訊
            skt.send(rst.encode())

            # 7. 關閉連結通路
            skt.close()

        if __name__ == "__main__":
            print("Starting tcp server.......")
            tcp_srv()
            print("Ending tcp server.......")
            
    # TCP客戶端案例:
    import socket
    def tcp_clt():
        # 1. 建立通訊socket
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 2. 連結對方,請求跟對方建立通路
        addr = ("127.0.0.1", 8998)
        sock.connect(addr)
        # 3. 傳送內容到對方伺服器
        msg = "I love wangxiaojing"
        sock.send(msg.encode())
        # 4. 接受對方的反饋
        rst =  sock.recv(500)
        print(rst.decode())
        # 5. 關閉連結通路
        sock.close()

if __name__ == "__main__":
    tcp_clt()

#=========================FTP程式設計=========================
# FTP(FileTransferProtocal)檔案傳輸協議
# 用途: 定製一些特殊的上傳下載檔案的服務
# 使用者分類: 登陸FTP伺服器必須有一個賬號
    # Real賬戶: 註冊賬戶
    # Guest賬戶: 可能臨時對某一類人的行為進行授權
    # Anonymous賬戶: 匿名賬戶,允許任何人
# FTP工作流程
    1. 客戶端連結遠端主機上的FTP伺服器
    2. 客戶端輸入使用者名稱和密碼(或者“anonymous”和電子郵件地址)
    3. 客戶端和伺服器進行各種檔案傳輸和資訊查詢操作
    4. 客戶端從遠端FTP伺服器退出,結束傳輸   
    
# FTP檔案表示
    # 分三段表示FTP伺服器上的檔案
    # HOST: 主機地址,類似於 ftp.mozilla.org, 以ftp開頭
    # DIR:目錄, 表示檔案所在本地的路徑,例如 pub/android/focus/1.1#RC1/ 
    # File: 檔名稱, 例如 Klar#1.1#RC1.apk
    # 如果想完整精確表示ftp上某一個檔案,需要上述三部分組合在一起
# FTP案例:
    # 需要匯入相應包,主要是ftplib
    import ftplib # 關於FTP的操作都在這個包裡邊
    import os
    import socket

    # 三部分精確表示在ftp伺服器上的某一個檔案
    # 好多公開ftp伺服器訪問會出錯或者沒有反應
    HOST = "ftp.acc.umu.se"
    DIR = 'Public/EFLIB/'
    FILE = 'README'

    # 1. 客戶端連結遠端主機上的FTP伺服器
    try:
        f = ftplib.FTP()
        # 通過設定除錯級別可以方便除錯
        f.set_debuglevel(2)
        # 連結主機地址
        f.connect(HOST)
    except Exception as e:
        print(e)
        exit()
    print("***Connected to host {0}".format(HOST))

    # 2. 客戶端輸入使用者名稱和密碼(或者“anonymous”和電子郵件地址)
    try:
        # 登入如果沒有輸入使用者資訊,則預設使用匿名登入
        f.login()
    except Exception as e:
        print(e)
        exit()
    print("***Logged in as 'anonymous'")

    # 3. 客戶端和伺服器進行各種檔案傳輸和資訊查詢操作
    try:
        # 更改當前目錄到指定目錄
        f.cwd(DIR)
    except Exception as e:
        print(e)
        exit()
    print("*** Changed dir to {0}".format(DIR))

    try:
        # 從FTP伺服器上下載檔案
        # 第一個引數是ftp命令
        # 第二個引數是回撥函式
        # 此函式的意思是,執行RETR命令,下載檔案到本地後,執行回撥函式
        f.retrbinary('RETR {0}'.format(FILE), open(FILE, 'wb').write)
    except Exception as e:
        print(e)
        exit()

    # 4. 客戶端從遠端FTP伺服器退出,結束傳輸
    f.quit()
    
#=========================Mail程式設計=========================
## 電子郵件的歷史
# 起源
    # 1969 Leonard K. 教授發給同時的 “LO”
    # 1971 美國國防部自主的阿帕網(Arpanet)的通訊機制
    # 通訊地址裡用"@" 
    # 1987年中國的第一份電子郵件  
    # "Across the Great Wall we can reach every corner in the world"

# 管理程式
    # Euroda使郵件普及 
    # Netscape,outlook,forxmail後來居上
    # Hotmal使用瀏覽器傳送郵件i
# 參考資料
    # [官網](https://docs.python.org/3/library/email.mime.html)
    
## 郵件工作流程
# MUA(MailUserAgent)郵件使用者代理
# MTA(MailTransferAgent)郵件傳輸代理
# MDA(MailDeliveryAgent)郵件投遞代理
# [email protected], 老師,北京海淀
# [email protected], 學生,上海江岸區
# 流程
    1. MUA#>MTA, 郵件已經在伺服器上了
    2. qq MTA#>.........#>sina MTA, 郵件在新浪的伺服器上
    3. sina MTA#> sina MDA, 此時郵件已經在你的郵箱裡了
    4. sina MDA #> MUA(Foxmail/Outlook), 郵件下載到本地電腦
   
# 編寫程式
    # 傳送:  MUA#>MTA with SMTP:SimpleMailTransferProtocal,包含MTA#>MTA
    # 接受:  MDA#>MUA with POP3 and IMAP:PostOfficeProtocal v3 and  InternetMessageAccessProtocal v4
    
# 準備工作
    # 註冊郵箱(以qq郵箱為例)
    # 第三方郵箱需要特殊設定, 以qq郵箱為例
        # 進入設定中心
        # 取得授權碼
        
# Python for mail
    # SMTP協議負責傳送郵件
    # 使用smtplib模組傳送郵件 
    # 1、使用email模組構建郵件
        # 純文字郵件
        # 案例:

    # 匯入相應的包
    import smtplib
    from email.mime.text import MIMEText
    # MIMEText三個主要引數
    # 1. 郵件內容
    # 2. MIME子型別,在此案例我們用plain表示text型別
    # 3. 郵件編碼格式
    msg = MIMEText("Hello, i am beijing tulingxueyuan ", "plain", "utf-8")
    # 發件人的email地址
    from_addr = "[email protected]"
    # 此處密碼是經過申請設定後的授權碼,不是不是不是你的qq郵箱密碼
    from_pwd = "hjpovygcxmrshhcj"
    # 收件人資訊
    to_addr = "[email protected]"
    # 輸入SMTP伺服器地址
    # 騰訊qq郵箱所的smtp地址是 smtp.qq.com
    smtp_srv = "smtp.qq.com"
    try:
            # 加密傳輸
        # 第一個是伺服器地址,但一定是bytes格式,所以需要編碼
        # 第二個引數是伺服器的接受訪問埠
        # srv = smtplib.SMTP_SSL(smtp_srv.encode(), 465) #SMTP協議預設埠25
        # qq郵箱要求使用 TLS加密傳輸
        server = smtplib.SMTP(smtp_srv.encode(), 25) # SMTP協議預設埠是25
            server.starttls()
            # 設定除錯級別
            # 通過設定除錯等級,可以清楚的看到傳送郵件的互動步驟
            server.set_debuglevel(1)
        #登入郵箱傳送
        srv.login(from_addr, from_pwd)
        # 傳送郵件
        # 三個引數
        # 1. 傳送地址
        # 2. 接受地址,必須是list形式
        # 3. 傳送內容,作為字串傳送
        srv.sendmail(from_addr, [to_addr], msg.as_string())
        srv.quit()
    except Exception as e:
        print(e)

  # HTML格式郵件傳送
      # 準備HTML程式碼作為內容
      # 把郵件的subtpye設為html
      # 傳送
      # 案例片段,其他與TEXT傳送一樣:
    mail_content = """
      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Title</title>
      </head>
      <body>
      <h1> 這是一封HTML格式郵件</h1>
      </body>
      </html>