【问题标题】:Flutter: Listening and writing to a socket in a single stateful widgetFlutter:在单个有状态小部件中侦听和写入套接字
【发布时间】:2022-01-22 10:38:21
【问题描述】:

我已经有一段时间没有开发过 Flutter 应用程序了,也没有开发过套接字级别的应用程序。我正在尝试学习如何使单个有状态小部件侦听套接字。小部件可以轻松地将数据写入套接字。

我正在尝试学习解决问题的方法,以便弄清楚如何组织我的应用程序。

编辑:我有一个草率的版本,所以更清楚我想要完成什么。

// Assume this will be stored in some BLoC 
// that will be available to any widget that needs it.
Socket socket;

void main() async {
  socket = await Socket.connect('192.168.139.194', 80);
  //can write to client with socket.write("...");

  socket.listen(handleClient);
  // handleClient takes care of responding to message from client

  runApp(MyApp(sock));
}

void handleClient(Uint8List data) {
  // Show the address and port of the client
  print('Connection from '
    '${socket.remoteAddress.address}:${socket.remotePort}');

  // Show what the client said
  print("client listen  : ${String.fromCharCodes(data).trim()}");

  // Send acknowledgement to client
  socket.write("Hello from simple server!\n");
}

【问题讨论】:

    标签: flutter sockets write listen


    【解决方案1】:

    您可以使用Socket.connect() 连接客户端的套接字,使用ServerSocket.bind() 监听服务器端的传入连接。您可以使用socket.write(message); 通过套接字发送数据,并使用socket.listen(); 监听响应。

    示例客户端代码:

    Socket.connect("localhost", 9999).then((socket) {
      print('client connected : ${socket.remoteAddress.address}:${socket.remotePort}');
    
      socket.listen((data) {
        print("client listen  : ${String.fromCharCodes(data).trim()}");
      }, onDone: () {
        print("client done");
        socket.destroy();
      });
    
      socket.write(message);
    });
    

    示例服务器代码:

      void listen() {
        ServerSocket.bind(InternetAddress.anyIPv4, 9999).then((ServerSocket server) {
          server.listen(handleClient);
        });
      }
    
      void handleClient(Socket client) {
        print('server incoming connection from ${client.remoteAddress.address}:${client.remotePort}');
        client.listen((data) {
          print("server listen  : ${String.fromCharCodes(data).trim()}");
          setState(() {
            _incomingMessage = String.fromCharCodes(data).trim();
          });
        }, onDone: () {
          print("server done");
        });
        client.close();
      }
    

    请参考:https://jamesslocum.com/blog/post/67566023889

    您可以在 github 上找到 clientserver 的完整源代码


    更新:如果您想使用相同的小部件可以听和写,您可以参考此代码。你应该开始在构造函数中监听套接字。

    示例代码:

    import 'dart:io';
    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      MyApp({Key? key}) : super(key: key) {
        listen();
      }
    
      void socketSend(String message) {
        Socket.connect("localhost", 9999).then((socket) {
          print('client connected : ${socket.remoteAddress.address}:${socket.remotePort}');
    
          socket.listen((data) {
            print("client listen  : ${String.fromCharCodes(data).trim()}");
          }, onDone: () {
            print("client done");
            socket.destroy();
          });
    
          socket.write(message);
        });
      }
    
      void listen() {
        ServerSocket.bind(InternetAddress.anyIPv4, 9999).then((ServerSocket server) {
          server.listen(handleClient);
        });
      }
    
      void handleClient(Socket client) {
        print('server incoming connection from ${client.remoteAddress.address}:${client.remotePort}');
        client.listen((data) {
          print("server listen  : ${String.fromCharCodes(data).trim()}");
        }, onDone: () {
          print("server done");
        });
        client.close();
      }
    
      @override
      Widget build(BuildContext context) {
        final myController = TextEditingController();
    
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: Scaffold(
            appBar: AppBar(
              title: const Text("socket test"),
            ),
            body: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  TextField(controller: myController),
                  ElevatedButton(onPressed: () => socketSend(myController.text), child: const Text("Send")),
                ],
              ),
            ),
          ),
        );
      }
    } 
    

    端口80 也是HTTP 的保留端口。您不应使用此端口进行测试。

    【讨论】:

    • 我一定不是很清楚,我希望一个无状态小部件能够从/向同一个套接字读取和写入我将修改我的问题。
    • 嗨@Nefarious,我更新了我的答案。请检查。
    猜你喜欢
    • 1970-01-01
    • 2016-11-19
    • 2019-09-23
    • 2019-06-10
    • 2018-09-01
    • 1970-01-01
    • 2011-12-10
    • 1970-01-01
    • 2023-04-01
    相关资源
    最近更新 更多