Linux開發板(樹莓派)和伺服器進行雙向通訊(socket)

Mosu's_tech_blog發表於2022-03-29

前言

​ 物聯網是目前嵌入開發必備的屬性之一,我們常常需要把自己開發板和雲端進行互動,本篇博文就記錄一下。

​ 使用Socket來實現Linux開發板和伺服器進行雙向通訊,Python中是預設整合了socket模組的,我們就不需要下載了。

​ 實際上,只要是能執行Python的環境,就可以和伺服器進行雙向通訊,你不必侷限於樹莓派。

一、開發環境

PC系統:windows 10

Linux開發板:樹莓派4B

伺服器:阿里雲 ECS

程式語言:Python

二、通訊程式碼

​ 我認為我的註釋是十分詳細的,實現簡單用函式來呼叫(貼程式碼方便),自己開發時,可以用類封裝一下。

記得先在伺服器把要用的埠新增到安全組裡面。下面的程式碼伺服器端你不需要做任何修改,開發板端你把公網ip修改成自己的就可以跑通了。

(1)伺服器端
import socket
import sys


def socket_service_data():
    # 連線
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.bind(ADDR)  # 在不同主機或者同一主機的不同系統下使用實際ip
        s.listen(10)
    except socket.error as msg:
        print(msg)
        sys.exit(1)
    print("Wait for Connection..................")
	sock, addr = s.accept()
    
    while True:
        # 收
        buf = sock.recv(BUFSIZ)  # 接收資料
        buf1 = buf.decode('utf-8')  # 解碼
        if not buf:
            break
        print('Received message:', buf1)
        # return buf
        # 發
        buf = input("input data:")  # 輸入要傳輸的資料
        if not buf:
            break
        sock.send(buf.encode())  # 將要傳輸的資料編碼傳送,如果是字元資料就必須要編碼傳送
    # 關閉socket
    sock.close()


if __name__ == '__main__':
    # 初始化
    name = socket.gethostname()
    HOST = socket.gethostbyname(name)  # 獲取阿里雲伺服器私網IP,使用ifconfig可查詢
    PORT = 7000
    BUFSIZ = 1024
    ADDR = (HOST, PORT)

    socket_service_data()

(2)開發板端
import socket
import sys


def sock_client_data():
    # 連線
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect(ADDR)
    except socket.error as msg:
        print(msg)
        print(sys.exit(1))

    while True:
        # 發
        data = input("input data:")  # 輸入要傳輸的資料
        if not data:
            break
        s.send(data.encode('utf-8'))  # 將要傳輸的資料編碼傳送,如果是字元資料就必須要編碼傳送
        # 收
        data = s.recv(BUFSIZ)
        if not data:
            break
        print(data.decode('utf-8'))
    # 關閉socket
    s.close()


if __name__ == '__main__':
    # 初始化
    HOST = '99.100.101.102'  # 比如 99.100.101.102是你的伺服器的公網IP
    PORT = 7000  # IP開放的socket埠
    BUFSIZ = 1024
    ADDR = (HOST, PORT)

    sock_client_data()

開發板發一句,伺服器接受一句,伺服器發一句,開發板再接受一句。

三、通訊程式碼解釋

​ 程式碼邏輯沒什麼說的,簡單說下socket模組中呼叫的一下方法。

1.sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)

:socket.AF_INET IPv4(預設),socket.SOCK_STREAM 流式socket , for TCP (預設),預設是0 我上面都沒填系統就會根據地址格式和套接類別,自動選擇一個合適的協議。

2.sk.bind(address)

:s.bind(address) 將套接字繫結到地址。address地址的格式取決於地址族。

在AF_INET下,以元組(host,port)的形式表示地址。

3.sk.listen(backlog)

:開始監聽傳入連線。backlog指定在拒絕連線之前,可以掛起的最大連線數量。backlog等於5,表示核心已經接到了連線請求,但伺服器還沒有呼叫accept進行處理的連線個數最大為5。這個值不能無限大,因為要在核心中維護連線佇列。

4.sk.accept()

:接受連線並返回(conn,address),其中conn是新的套接字物件,可以用來接收和傳送資料。address是連線客戶端的地址。接收TCP 客戶的連線(阻塞式)等待連線的到來。

5.sk.connect(address)

:連線到address處的套接字。一般,address的格式為元組(hostname,port),如果連線出錯,返回socket.error錯誤。

6.sk.recv(bufsize[,flag])

:接受套接字的資料。資料以字串形式返回,bufsize指定最多可以接收的數量。flag提供有關訊息的其他資訊,通常可以忽略。

7.sk.send(string[,flag])

:將string中的資料傳送到連線的套接字。返回值是要傳送的位元組數量,該數量可能小於string的位元組大小。即:可能未將指定內容全部傳送。

8.sk.close()

:關閉套接字

9.socket.gethostname()

:gethostname()返回執行程式所在的計算機的主機名

後言

如果有相關的問題,歡迎在評論區交流,博主知必答。

參考文章連結

樹莓派4B和阿里雲伺服器進行通訊

網路程式設計-Python的socket庫

相關文章