python - 用于 mWebSocket 服务器的 Python WebSocket 客户端
问题描述
我正在尝试在 python 中构建一个 WebSocket 客户端,它通过以太网电缆每秒连接到一个 Arduino Uno,它上面有一个基于 mWebSocket 库的 WebSocket 服务器。工作的 Arduino 代码如下所示:
#include <WebSocketServer.h>
using namespace net;
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[]{0xA8, 0x61, 0x0A, 0xAE, 0x69, 0x13};
IPAddress ip(198, 162, 1, 177);
IPAddress gateway(0,0,0,0);
IPAddress DNSserver(0,0,0,0);
IPAddress subnet(255,255,255,0);
constexpr uint16_t port = 80;
WebSocketServer wss{port};
void setup() {
// You can use Ethernet.init(pin) to configure the CS pin
Ethernet.init(10); // Most Arduino shields
//Ethernet.init(5); // MKR ETH shield
//Ethernet.init(0); // Teensy 2.0
//Ethernet.init(20); // Teensy++ 2.0
//Ethernet.init(15); // ESP8266 with Adafruit Featherwing Ethernet
//Ethernet.init(33); // ESP32 with Adafruit Featherwing Ethernet
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println("Ethernet WebServer Example");
// start the Ethernet connection and the server:
Ethernet.begin(mac,ip,DNSserver,gateway,subnet);
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true) {
delay(1); // do nothing, no point running without Ethernet hardware
}
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println("Ethernet cable is not connected.");
}
// start the server
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
wss.onConnection([](WebSocket & ws) {
const auto protocol = ws.getProtocol();
if (protocol) {
Serial.print(F("Client protocol: "));
Serial.println(protocol);
}
ws.onMessage([](WebSocket & ws, const WebSocket::DataType dataType,
const char *message, uint16_t length) {
switch (dataType) {
case WebSocket::DataType::TEXT:
Serial.print(F("Received: "));
Serial.println(message);
break;
case WebSocket::DataType::BINARY:
Serial.println(F("Received binary data"));
break;
}
ws.send(dataType, message, length);
});
ws.onClose([](WebSocket &, const WebSocket::CloseCode, const char *,
uint16_t) {
Serial.println(F("Disconnected"));
});
Serial.print(F("New client: "));
Serial.println(ws.getRemoteIP());
const char message[] {"Hello from Arduino server!"};
ws.send(WebSocket::DataType::TEXT, message, strlen(message));
});
wss.begin();
Serial.println(Ethernet.localIP());
}
void loop() {
wss.listen();
}
我已经构建了一个 python 套接字客户端来与这个 Arduino 交互,并希望打印消息“来自 Arduino 服务器的你好!” 通过每个连接发送给客户端。
#!/usr/bin/python3
import asyncio
import websockets
import socket
import time
import datetime
import struct
starttime = time.time() # start value for timed data acquisition
# setup socket 1
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s1.connect(("198.162.1.177",80))
s1.sendall(b'GET / HTTP/1.1 400')
if True:
print('Connected')
def acquire():
data = s1.recv(10000)
print(data)
while True:
acquire()
time.sleep(1.0 - ((time.time() - starttime) % 1.0)) # continue every (2.0 seconds)
s1.close()
但是,当我运行上面的代码时。我获得:
Connected
b'H'
b'TTP/1.1 400 Bad Request\r\n'
b''
b''
b''
b''
b''
我在这里缺少什么,我认为连接没有完全建立,即使我可以从我的电脑上 ping Arduino。我是否需要以不同的方式为 WebSocket 客户端考虑 HTTP 标头?
解决方案
Websocket 连接是由带有升级标头的 HTTP 请求建立的,该标头指定连接客户端想要升级到 Websocket 协议。当服务器收到此消息并在请求中找到升级标头时,它会验证它是否支持的升级结束并将底层连接升级到 websocket 连接。这是您似乎缺少的东西。
此外,当您在客户端代码中导入 websockets 时。您可以使用为您完成这项工作的库函数,您只需使用请求 URL 中指定的“ws/wss”发出 GET 请求。
推荐阅读
- matlab - 如何裁剪出复杂形状图像中的所有黑色像素?
- webpack - 在本地或全局导入组件之间是否存在大小差异?
- javascript - ReactJs this.props.history.push() 不工作
- firebase - 如何复制 Firebase 项目?(小白)
- jquery - 显示来自 URL 的特定 json 数据
- java - how to get summation of pair(key) values in a map in java?
- autocomplete - Atom 自动完成空格/封闭标记
- angular - 'number' 类型的参数不能分配给 angular2 中的 'string' 类型的参数。
- android - 使用数据库在 EditText 中搜索到 Listview
- c++ - 为什么我的 switch 语句对一半的情况没有响应?