前言
物聯網是目前嵌入開發必備的屬性之一,我們常常需要把自己開發板和雲端進行交互,本篇博文就記錄一下。
使用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()返回運行程序所在的計算機的主機名
后言
如果有相關的問題,歡迎在評論區交流,博主知必答。
參考文章鏈接