网络套接字意外关闭
websockets closing unexpectedly
4 月 13 日更新: dart 代码始终如一
背景:
我的电视(三星 2019 RU7000)提供了一个安全的 websocket 连接,可以发送 json 数据包来远程控制它。例如
"method":"ms.remote.control",
"params":{ "Cmd": "Click", "DataOfCmd":"KEY_MUTE" }
可以发送使电视静音。
为了启用访问,已完成握手。客户端连接到 wss://ip:8002/api/v2/samsung.remote.control?name=value
,其中 name
的值是 base64 编码的字符串。连接成功后,电视上会弹出window,需要接受。如果用户接受请求,电视将发送包含令牌的 JSON 响应:
"data":{
"clients":[ ... ],
"id":"...",
"token":"28852140"
},
"event":"ms.channel.connect"
此令牌用于通过将 &token=value
附加到 URL 来验证具有相同名称的连接。在用户接受弹出窗口之前发送命令将被忽略。
什么有效
wscat
和 curl
的命令行方法正在运行。电视显示弹出窗口并发送响应:
$ wscat -n -c https://192.168.0.227:8002/api/v2/channels/samsung.remote.control?name=aW9Ccm9rZXI=
Connected (press CTRL+C to quit)
< {"data":{"clients":[...], "id":"...", "token":"57940060"}, "event":"ms.channel.connect"}
飞镖 - dart.io.WebSocket
以下代码触发弹出窗口并获得响应。
WebSocket ws = await WebSocket.connect(url,
compression: CompressionOptions.compressionOff);
ws.pingInterval = Duration(seconds: 10000);
ws.listen(print, onError: print, onDone: () {
print("done");
print(ws.closeCode);
print(ws.closeReason);
});
await Future.delayed(Duration(seconds: 30));
ws.close();
问题
我想使用 python 连接到 websocket,验证我的会话并发送远程控制命令。这不适用于以下实现。
python - websocket liris
弹窗没有出现,电视也没有反应。套接字没有关闭。
from websocket import create_connection
from ssl import CERT_NONE
sock = create_connection(url, sslopt={"cert_reqs": CERT_NONE})
print(sock.recv())
python - websockets aaugustin
弹窗也没有出现,似乎连接被电视关闭了。
from websockets.client import connect, WebSocketClientProtocol
import ssl
import asyncio
async def connect():
async with connect(url, ssl=ssl.CERT_NONE) as websocket:
res = await websocket.recv()
print(res)
asyncio.get_event_loop().run_until_complete(connect())
wireshark log 表明它正在发送 HTTP GET 请求升级 websocket。电视通过关闭与 FIN 和 RST 的连接来响应。
观察
与公开可用的 websocket 服务器的连接与我遇到的问题不同。
许多适用于 python 的流行遥控器都将这两个 websocket 库作为实现的解决方案。 None 其中对我有用。
比较 python 实现和命令行工具发送的数据包对我来说没有明显的区别。
wscat 每四秒向电视发送一个 80 字节长的数据包。我想这是 ping/pong.
我该如何进一步调查?
为什么不使用更高级别的 Python 模块,例如 requests
?
您可以尝试以下方法:
import requests
params = (
('name', 'aW9Ccm9rZXI='),
)
response = requests.get('https://192.168.0.227:8002/api/v2/channels/samsung.remote.control', params=params)
嗯....我对使用 python websockets 的 websockets 连接有一些经验。
在文章中,您指出您的 websockets 连接将自动与服务器断开连接。
我认为是 websockets 模块中的机制调用 "ping-pong" 导致了这个问题。
机制默认状态为true,这意味着你会定期向websocket服务器发送一个ping信号,如果服务器没有向你发送pong,模块将认为服务器已经shutdown.So你需要做的只是设置 "ping-pong"
status to False.
async def connect():
async with connect(url, ssl=ssl.CERT_NONE,close_timeout = None,ping_interval = None) as websocket:
res = await websocket.recv()
print(res)
asyncio.get_event_loop().run_until_complete(connect())
以上都是我个人的看法,大家可以试试看
试试 Tornado 的 websocket 实现怎么样?
async def samsung_ws():
ws_req = HTTPRequest("wss://ip:8002/api/v2/samsung.remote.control?name=value", validate_cert=False)
ws = await websocket_connect(ws_req)
ws.write_message("hello")
while True:
msg = await ws.read_message()
if not msg:
break
print(msg)
根据网络服务器的构建方式,您可能需要在连接到 websocket 之前请求网页,因为在您的 wscat
示例中我注意到您使用的是 https://
而不是 wss://
.
你能 post 一个飞镖样本 运行(使用了 url
)吗?
4 月 13 日更新: dart 代码始终如一
背景:
我的电视(三星 2019 RU7000)提供了一个安全的 websocket 连接,可以发送 json 数据包来远程控制它。例如
"method":"ms.remote.control",
"params":{ "Cmd": "Click", "DataOfCmd":"KEY_MUTE" }
可以发送使电视静音。
为了启用访问,已完成握手。客户端连接到 wss://ip:8002/api/v2/samsung.remote.control?name=value
,其中 name
的值是 base64 编码的字符串。连接成功后,电视上会弹出window,需要接受。如果用户接受请求,电视将发送包含令牌的 JSON 响应:
"data":{
"clients":[ ... ],
"id":"...",
"token":"28852140"
},
"event":"ms.channel.connect"
此令牌用于通过将 &token=value
附加到 URL 来验证具有相同名称的连接。在用户接受弹出窗口之前发送命令将被忽略。
什么有效
wscat
和 curl
的命令行方法正在运行。电视显示弹出窗口并发送响应:
$ wscat -n -c https://192.168.0.227:8002/api/v2/channels/samsung.remote.control?name=aW9Ccm9rZXI=
Connected (press CTRL+C to quit)
< {"data":{"clients":[...], "id":"...", "token":"57940060"}, "event":"ms.channel.connect"}
飞镖 - dart.io.WebSocket
以下代码触发弹出窗口并获得响应。
WebSocket ws = await WebSocket.connect(url,
compression: CompressionOptions.compressionOff);
ws.pingInterval = Duration(seconds: 10000);
ws.listen(print, onError: print, onDone: () {
print("done");
print(ws.closeCode);
print(ws.closeReason);
});
await Future.delayed(Duration(seconds: 30));
ws.close();
问题
我想使用 python 连接到 websocket,验证我的会话并发送远程控制命令。这不适用于以下实现。
python - websocket liris
弹窗没有出现,电视也没有反应。套接字没有关闭。
from websocket import create_connection
from ssl import CERT_NONE
sock = create_connection(url, sslopt={"cert_reqs": CERT_NONE})
print(sock.recv())
python - websockets aaugustin
弹窗也没有出现,似乎连接被电视关闭了。
from websockets.client import connect, WebSocketClientProtocol
import ssl
import asyncio
async def connect():
async with connect(url, ssl=ssl.CERT_NONE) as websocket:
res = await websocket.recv()
print(res)
asyncio.get_event_loop().run_until_complete(connect())
wireshark log 表明它正在发送 HTTP GET 请求升级 websocket。电视通过关闭与 FIN 和 RST 的连接来响应。
观察
与公开可用的 websocket 服务器的连接与我遇到的问题不同。
许多适用于 python 的流行遥控器都将这两个 websocket 库作为实现的解决方案。 None 其中对我有用。
比较 python 实现和命令行工具发送的数据包对我来说没有明显的区别。
wscat 每四秒向电视发送一个 80 字节长的数据包。我想这是 ping/pong.
我该如何进一步调查?
为什么不使用更高级别的 Python 模块,例如 requests
?
您可以尝试以下方法:
import requests
params = (
('name', 'aW9Ccm9rZXI='),
)
response = requests.get('https://192.168.0.227:8002/api/v2/channels/samsung.remote.control', params=params)
嗯....我对使用 python websockets 的 websockets 连接有一些经验。 在文章中,您指出您的 websockets 连接将自动与服务器断开连接。
我认为是 websockets 模块中的机制调用 "ping-pong" 导致了这个问题。
机制默认状态为true,这意味着你会定期向websocket服务器发送一个ping信号,如果服务器没有向你发送pong,模块将认为服务器已经shutdown.So你需要做的只是设置 "ping-pong"
status to False.
async def connect():
async with connect(url, ssl=ssl.CERT_NONE,close_timeout = None,ping_interval = None) as websocket:
res = await websocket.recv()
print(res)
asyncio.get_event_loop().run_until_complete(connect())
以上都是我个人的看法,大家可以试试看
试试 Tornado 的 websocket 实现怎么样?
async def samsung_ws():
ws_req = HTTPRequest("wss://ip:8002/api/v2/samsung.remote.control?name=value", validate_cert=False)
ws = await websocket_connect(ws_req)
ws.write_message("hello")
while True:
msg = await ws.read_message()
if not msg:
break
print(msg)
根据网络服务器的构建方式,您可能需要在连接到 websocket 之前请求网页,因为在您的 wscat
示例中我注意到您使用的是 https://
而不是 wss://
.
你能 post 一个飞镖样本 运行(使用了 url
)吗?