我是websocket的新手,并试图使用Dart/flutter编写的客户端连接到使用Autobahn编写的Python服务器。
由于Autobahn的服务器示例文档没有给出使用ws://
地址的情况,我试图根据其服务器工厂文档自己创建这样的服务器,但失败了。
服务器代码如下所示
# from autobahn.twisted.websocket import WebSocketServerProtocol
from autobahn.asyncio.websocket import WebSocketServerProtocol
class MyServerProtocol(WebSocketServerProtocol):
def onConnect(self, request):
print("Client connecting: {}".format(request.peer))
def onOpen(self):
print("WebSocket connection open.")
def onMessage(self, payload, isBinary):
if isBinary:
print("Binary message received: {} bytes".format(len(payload)))
else:
print("Text message received: {}".format(payload.decode('utf8')))
# echo back message verbatim
self.sendMessage(payload, isBinary)
def onClose(self, wasClean, code, reason):
print("WebSocket connection closed: {}".format(reason))
if __name__ == '__main__':
import asyncio
from autobahn.asyncio.websocket import WebSocketServerFactory
factory = WebSocketServerFactory(url='ws://myhost.com/somepat:9001')
factory.protocol = MyServerProtocol
loop = asyncio.get_event_loop()
coro = loop.create_server(factory, '127.0.0.1', 9001)
server = loop.run_until_complete(coro)
try:
print('starting server ...')
loop.run_forever()
except KeyboardInterrupt:
pass
finally:
server.close()
loop.close()
客户端代码改编自flutter文档,只有通道是我自己的:
import 'package:flutter/foundation.dart';
import 'package:web_socket_channel/io.dart';
import 'package:flutter/material.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
final title = 'WebSocket Demo';
return MaterialApp(
title: title,
home: MyHomePage(
title: title,
// channel: IOWebSocketChannel.connect('ws://echo.websocket.org'),
channel: IOWebSocketChannel.connect('ws://myhost.com/somepat:9001'),
),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
final WebSocketChannel channel;
MyHomePage({Key key, @required this.title, @required this.channel})
: super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
TextEditingController _controller = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Form(
child: TextFormField(
controller: _controller,
decoration: InputDecoration(labelText: 'Send a message'),
),
),
StreamBuilder(
stream: widget.channel.stream,
builder: (context, snapshot) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 24.0),
child: Text(snapshot.hasData ? '${snapshot.data}' : ''),
);
},
)
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _sendMessage,
tooltip: 'Send message',
child: Icon(Icons.send),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
void _sendMessage() {
if (_controller.text.isNotEmpty) {
widget.channel.sink.add(_controller.text);
}
}
@override
void dispose() {
widget.channel.sink.close();
super.dispose();
}
}
预期运行上述服务器和客户端代码,我希望看到来自客户端的任何输入字符串从服务器返回,并显示在客户端智能手机上文本条目下方的UI上。
观察什么也回不来。来自客户端的日志
Launching lib/main.dart on LIO AN00m in debug mode...
Running Gradle task 'assembleDebug'...
✓ Built build/app/outputs/flutter-apk/app-debug.apk.
Installing build/app/outputs/flutter-apk/app.apk...
Debug service listening on ws://127.0.0.1:54635/rsYDNkqGhYI=/ws
Syncing files to device LIO AN00m...
I/DecorView[](28048): old windowMode:1 new windoMode:1
I/AwareBitmapCacher(28048): init lrucache size: 2097152 pid=28048
D/stylus (28048): init stylus touchlistener.
I/Hwaps (28048): APS: EventAnalyzed: initAPS: version is 11.0.0.4
D/Hwaps (28048): Fpsrequest create,type:EXACTLY_IDENTIFY
D/Hwaps (28048): Fpsrequest create,type:EXACTLY_IDENTIFY
D/Hwaps (28048): Fpsrequest create,type:OPENGL_SETTING
D/Hwaps (28048): FpsController create
D/Hwaps (28048): APS: EventAnalyzed: reInitFpsPara :mBaseFps = 60; mMaxFps = 60
W/Settings(28048): Setting device_provisioned has moved from android.provider.Settings.Secure to android.provider.Settings.Global.
V/HiTouch_HiTouchSensor(28048): User setup is finished.
W/HwApsManager(28048): HwApsManagerService, registerCallback, start !
D/Hwaps (28048): APS: EventAnalyzed: registerCallbackInApsManagerService, mPkgName:com.example.flutter_websocket; result = true
W/InputMethodManager(28048): startInputReason = 4
I/InputMethodManager(28048): showSoftInput
W/InputMethodManager(28048): startInputReason = 3
V/AudioManager(28048): querySoundEffectsEnabled...
尝试我尝试了一些不同的地址字符串,比如
'ws://127.0.0.1:9001'
'ws://localhost:9001'
但是它们都不工作。
看来我缺乏一些基本的入门知识。我来自ZeroMQ世界,在那里所有的地址几乎都是隐藏实现细节的标签,这对像我这样的网络编程新手来说很友好,但似乎也阻止了我理解WebSocket协议。
我错在哪里,如何调试这种情况?如有任何提示,不胜感激。
您需要在python代码中输入pc/服务器的IP地址你可以通过运行ipconfig
来检查,你也应该在dart应用程序上输入相同的IP。localhost是一个主机名,指的是用来访问它的当前设备,其他设备不能访问其他localhost,但可以访问它们的IP地址。