简体   繁体   中英

Websocket: Working with Dart client and Autobahn-python server

I'm new to websocket and trying to use a client written in Dart/flutter to connect to a server written in Python using Autobahn.

Problem

Since Autobahn's server example documentation gives no case about using a ws:// address, I tried to create such a server myself based on its server factory docs , but it failed.

Code

server code looks like this

# 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()

client code adapted from flutter documentation , only the channel is my own:

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();
  }
}

Expected

Running the above server and client code, I expect to see any input string from the client get echoed back from the server and show on the UI below the text entry on the client smartphone.

Observation

Nothing comes back. The log from client side

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...

Attempts

I tried a few different address strings, such as

'ws://127.0.0.1:9001'

'ws://localhost:9001'

But none of them work.

Question

It seems that I lack some fundamental knowledge to get started. I come from the ZeroMQ world where all addresses are pretty much tags hiding implementation details, which was friendly to.network programming noobs like me, but also seems to prevent me from understanding the WebSocket protocol.

Where am I wrong and how to debug such a case? Any pointers are appreciated.

You need to enter the IP address of your pc/server in the python code you can check that out by running ipconfig , you should enter the same IP on the dart app as well. localhost is a hostname that refers to the current device used to access it, other devices cant access other localhosts but can access their IP address.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM