<button id="ssm6u"><optgroup id="ssm6u"></optgroup></button>
  • 跳轉至

    Socket通信

    概要

    socket幾乎是整個網絡通信的基礎,本文為大家講解Micropython中的Socket模塊。

    socket模塊 API文檔

    socket模塊中定義了許多和協議相關的宏,筆者整理出了下表:

    宏定義名稱 值(int) 功能 含義
    socket.AF_INET 2 地址簇 TCP/IP – IPv4
    socket.AF_INET 10 地址簇 TCP/IP - IPv6
    socket.SOCK_STREAM 1 套接字類型 TCP流
    socket.SOCK_DGRAM 2 套接字類型 UDP數據報
    socket.SOCK_RAW 3 套接字類型 原始套接字
    socket.SO_REUSEADDR 4 套接字類型 socket可重用
    socket.IPPROTO_TCP 16 IP協議號 TCP協議
    socket.IPPROTO_UDP 17 IP協議號 UDP協議
    socket.SOL_SOCKET 4095 套接字選項級別

    函數

    socket.getaddrinfo(host, port)

    函數說明:將主機域名(host)和端口(port)轉換為用于創建套接字的5元組序列。元組列表的結構如下:

    (family, type, proto, canonname, sockaddr)
    

    示例:

    >>> info = socket.getaddrinfo("127.0.0.1", 10000)
    >>> print(info)
    [(2, 1, 0, '127.0.0.1', ('127.0.0.1', 10000))]
    

    socket.socket([af, type, proto])

    函數說明:創建套接字。

    • af:地址

    • type:類型

    • proto:協議號

    *注意: 一般不指定proto參數,因為有些Micropython固件提供默認參數。 *
    示例:

    >>> s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    >>> print(s)
    <socket>
    

    socket.socket.setsockopt(level, optname, value)

    函數說明:根據選項值設置套接字。

    • level:套接字選項級別

    • optname:套接字的選項

    • value:可以是一個整數,也可以是一個表示緩沖區的bytes類對象。

    示例:

    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    

    socket.socket.bind(address)

    函數說明:以列表或元組的方式綁定地址和端口號。

    • address:一個包含地址和端口號的列表或元組。

    示例:

    addr = ("127.0.0.1",10000)
    s.bind(addr)
    

    socket.socket.listen([backlog])

    函數說明:監聽套接字,使服務器能夠接收連接。

    • backlog:接受套接字的最大個數,至少為0,如果沒有指定,則默認一個合理值。

    socket.socket.accept()

    函數說明:接收連接請求。
    注意:只能在綁定地址端口號和監聽后調用,返回conn和address。

    • conn:新的套接字對象,可以用來收發消息

    • address:連接到服務器的客戶端地址

    示例:

    conn,addr = s.accept()
    

    socket.socket.connect(address)

    函數說明:連接服務器。

    • address:服務器地址和端口號的元組或列表

    示例:

    host = "192.168.3.147"
    port = 100
    s.connect((host, port))
    

    socket.socket.send(bytes)

    函數說明:發送數據,并返回發送的字節數。

    • bytes:bytes類型數據

    示例:

    s.send("hello 1ZLAB, I am TCP Client")
    

    socket.socket.sendall(bytes)

    函數說明:與send()函數類似,區別是sendall()函數通過數據塊連續發送數據。

    • bytes:bytes類型數據

    示例:

    s.sendall("hello 1ZLAB, I am TCP Client")
    

    socket.socket.sendto(bytes, address)

    函數說明:發送數據,目標由address決定,用于UDP通信,返回發送的數據大小。

    • bytes:bytes類型數據

    • address:目標地址和端口號的元組

    示例:

    data = sendto("hello 1ZLAB", ("192.168.3.147", 100))
    

    socket.socket.recv(bufsize)

    函數說明:接收數據,返回接收到的數據對象。

    • bufsize:指定一次接收的最大數據量

    示例:

    data = conn.recv(1024)
    

    socket.socket.recvfrom(bufsize)

    函數說明:接收數據,用于UDP通信,并返回接收到的數據對象和對象的地址。

    • bufsize:指定一次接收的最大數據量

    示例:

    data,addr=fd.recvfrom(1024)
    

    socket.socket.settimeout(value)

    函數說明:設置超時時間,單位:秒。
    示例:

    s.settimeout(2)
    

    socket.socket.readline()

    函數說明:接收一行數據,遇換行符結束,并返回接收數據的對象 。

    socket.socket.write(buf)

    函數說明:將字節類型數據寫入套接字,并返回寫入數據的大小。

    socket.socket.close()

    函數說明:關閉套接字。
    示例:

    s.close()
    

    TCP服務端和客戶端通信示例

    確保你的ESP32和你的PC在同一局域網內。

    在接下來的示例中,我們以ESP32建立TCP服務端,在PC上編寫腳本 創建TCP客戶端,與服務器進行通信。

    ESP32 TCP服務端

    """
    ESP32 TCP Server
    """
    
    import socket
    from emp_wifi import Wifi
    
    port = 10000  #端口號
    listenSocket = None  #套接字
    
    try:
        # 注意:線連接到WiFi網絡!
        # 如果未連接到網絡,以下是連接到網絡的代碼
        # Wifi.connect()
        ip = Wifi.ifconfig()[0][0]   #獲取IP地址
        listenSocket = socket.socket()   #創建套接字
        listenSocket.bind((ip, port))   #綁定地址和端口號
        listenSocket.listen(1)   #監聽套接字, 最多允許一個連接
        listenSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)   #設置套接字
        print ('tcp waiting...')
    
        while True:
            print("accepting.....")
            conn, addr = listenSocket.accept()   #接收連接請求,返回收發數據的套接字對象和客戶端地址
            print(addr, "connected")
    
            while True:
                data = conn.recv(1024)   #接收數據(1024字節大?。?/span>
                if(len(data) == 0):   #判斷客戶端是否斷開連接
                    print("close socket")
                    conn.close()   #關閉套接字
                    break
                print(data)
                ret = conn.send(data)   #發送數據
    except:
        if(listenSocket):   #判斷套接字是否為空
            listenSocket.close()   #關閉套接字
    

    PC TCP客戶端

    # -*- coding: UTF-8 -*-
    # PC TCP Client
    
    import socket               # 導入 socket 模塊
    
    s = socket.socket()         # 創建 socket 對象
    host = '192.168.2.231'      # esp32 ip
    port = 10000                # 設置端口號
    
    s.connect((host, port))
    
    if __name__ == '__main__':
        while True:
            msg = raw_input('>>> ')
            s.send(msg)
    

    收看星球大戰字符動畫

    blinkenlights.nl網站提供的星球大戰Asciimation服務。它使用端口23上的telnet協議將數據流式傳輸給任何連接的人。

    接下來,讓我們建立一個TCP通信,在我們的REPL中觀看星球大戰。

    首先要導入套接字模塊:

    >>> import socket
    

    然后我們通過域名來獲取服務器的地址

    >>> addr_info = socket.getaddrinfo("towel.blinkenlights.nl", 23)
    

    getaddrinfo 函數實際上返回一個地址列表:

    [(2, 1, 0, 'towel.blinkenlights.nl', ('94.142.241.111', 23))]
    

    我們只需要獲取服務器的IP地址和端口,對應于該列表第一項的最后一個元組:

    >>> addr = addr_info[0][-1]
    

    建立一個socket對象,然后使用上面的IP地址和端口號與服務器進行連接:

    >>> s = socket.socket()
    >>> s.connect(addr)
    

    現在我們已經連接,我們可以獲取并顯示數據了:

    >>> while True:
    ...     data = s.recv(500)
    ...     print(str(data, 'utf8'), end='')
    ...
    

    當這個循環執行時,它應該開始顯示動畫(使用ctrl-C來中斷它)

    思考

    如何使用 Socket通信,來遠程點亮ESP32控制的LED呢?你將制定何種通信協議呢?


    韩国精品无码一区二区三区,精品无码一区二区三区AV,欧洲丰满美熟女乱又伦AV,亚洲午夜久久久影院伊人