Flutter TCP通信插件tcp_tunnel的使用

发布于 1周前 作者 bupafengyu 来自 Flutter

Flutter TCP通信插件tcp_tunnel的使用

标题

tcp_tunnel

内容

动机

该库的主要动机是帮助开发人员在复杂的网络拓扑中开发服务器、客户端和服务。

使用方法

有三种类型的隧道可以结合使用:

  1. 本地端口重定向: 将 listenPort(例如 3366)链接到 localTargetPort(例如 3306),实现双向数据流。

    Future<void> redirectLocalPort(int listenPort, int targetPort, {String targetHost = 'localhost'}) async {
      await TunnelLocalServer(listenPort, targetPort, targetHost: targetHost).start();
    }
    
  2. 桥接隧道: 连接 listenPort1listenPort2,实现数据流量交换。

    Future&lt;void&gt; bridgePorts(int listenPort1, int listenPort2) async {
      await TunnelBridge(listenPort1, listenPort2).start();
    }
    
  3. 客户端隧道: 将 remoteHost:remotePort 链接到 localTargetPort,实现双向数据传输。

    Future&lt;void&gt; clientTunnel(String remoteHost, int remotePort, int localTargetPort) async {
      var tunnel = Tunnel.connect(remoteHost, remotePort, localTargetPort);
    
      tunnel.onClose = ( t) {
        // 关闭连接,尝试重新连接...
      };
    }
    

CLI工具

你可以轻松地在任何支持Dart的平台上使用CLI工具 tcp_tunnel

激活CLI工具只需运行:

dart pub global activate tcp_tunnel

然后你可以为每个必要的场景创建隧道:

  1. 本地端口重定向:

    tcp_tunnel local %listenPort %targetPort %targetHost
    
    • %targetHost 是可选的,默认值为 localhost
  2. 桥接隧道:

    tcp_tunnel bridge %listenPort1 %listenPort2
    
  3. 客户端隧道:

    tcp_tunnel client %remoteHost %remotePort %localTargetPort
    

结合使用

要访问远程服务器X(没有公共地址)中的端口3306(MySQL):

  1. 在公共服务器Y(server-y.domain)上建立一个服务器桥接:

    tcp_tunnel bridge 8035 8036
    
  2. 在私有服务器X(具有私有MySQL数据库的服务器)上运行客户端隧道:

    tcp_tunnel client server-y.domain 8036 3306
    
  3. 运行mysql客户端指向隧道端口:

    mysql -u myuser -p -h server-y.domain -P 8035
    
  4. 如果希望扩展配置,可以在上述重定向中建立一个本地端口:

    tcp_tunnel local 3306 8035 server-y.domain
    

    现在,只需访问本地端口3306即可,就像访问标准MySQL数据库一样。 实际上,这个本地端口连接到一个远程私有服务器。

    mysql -u myuser -p -h localhost -P 3306
    

    或者默认设置(与上述相同):

    mysql -u myuser -p
    

安全性

请注意,隧道通信 未加密,且任何通过公共网络进行的连接都可能暴露其数据给潜在的安全风险。

特征和bug

请将功能请求和bug提交到 issue tracker

作者

Graciliano M. Passos: gmpassos@GitHub

赞助

不要害羞,展示一些爱,成为我们的 GitHub赞助商。你的支持对我们来说意义重大,并且保持代码充满活力!☕✨

许可证

Dart免费开源许可证 https://github.com/dart-lang/stagehand/blob/master/LICENSE


示例代码

import 'dart:io';

import 'package:tcp_tunnel/tcp_tunnel.dart';

void main() async {
  // 桥接:8035 &lt;-&gt; 8036
  await bridgePorts(8035, 8036);

  // 客户端:8036 &lt;-&gt; 3306
  await clientTunnel('localhost', 8036, 3306);

  // 客户端:3307 &lt;-&gt; 8035
  await redirectLocalPort(3307, 8035);

  ///// 最终隧道:
  // 3307 &lt;-&gt; 8035 &lt;-&gt; 8036 &lt;-&gt; 3306
}

Future&lt;void&gt; redirectLocalPort(int listenPort, int targetPort,
    {String targetHost = 'localhost'}) async {
  await TunnelLocalServer(listenPort, targetPort, targetHost: targetHost)
      .start();
}

Future&lt;void&gt; bridgePorts(int listenPort1, int listenPort2) async {
  await TunnelBridge(listenPort1, listenPort2).start();
}

Future&lt;void&gt; clientTunnel(
    String remoteHost, int remotePort, int localTargetPort) async {
  var tunnel = Tunnel.connect(remoteHost, remotePort, localTargetPort);

  tunnel.onClose = (t) {
    print('** Tunnel Closed');
    exit(1);
  };
}

更多关于Flutter TCP通信插件tcp_tunnel的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter TCP通信插件tcp_tunnel的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中进行TCP通信,tcp_tunnel 插件是一个非常有用的工具。下面是一个使用 tcp_tunnel 插件进行TCP通信的示例代码。该示例展示了如何建立TCP连接、发送和接收数据。

首先,确保在你的 pubspec.yaml 文件中添加 tcp_tunnel 依赖:

dependencies:
  flutter:
    sdk: flutter
  tcp_tunnel: ^x.y.z  # 请将x.y.z替换为最新版本号

然后运行 flutter pub get 来获取依赖。

接下来,在你的 Dart 代码中,你可以按照以下步骤使用 tcp_tunnel 插件:

import 'package:flutter/material.dart';
import 'package:tcp_tunnel/tcp_tunnel.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  TcpTunnel? _tcpTunnel;
  TextEditingController _controller = TextEditingController();
  String _response = '';

  @override
  void initState() {
    super.initState();
    initTcpTunnel();
  }

  void initTcpTunnel() async {
    _tcpTunnel = TcpTunnel(
      host: 'example.com', // 替换为你的服务器地址
      port: 12345,         // 替换为你的服务器端口
    );

    _tcpTunnel!.connect();

    _tcpTunnel!.dataStream.listen((data) {
      setState(() {
        _response = String.fromCharCodes(data);
      });
    });

    _tcpTunnel!.errorStream.listen((error) {
      print('Error: $error');
    });
  }

  void _sendMessage() async {
    if (_tcpTunnel!.isConnected) {
      String message = _controller.text;
      List<int> messageBytes = message.codeUnits;
      _tcpTunnel!.sendData(messageBytes);
      _controller.clear();
    } else {
      print('TCP Tunnel is not connected');
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('TCP Tunnel Example'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              TextField(
                controller: _controller,
                decoration: InputDecoration(labelText: 'Message'),
                maxLines: 4,
              ),
              SizedBox(height: 16),
              ElevatedButton(
                onPressed: _sendMessage,
                child: Text('Send Message'),
              ),
              SizedBox(height: 16),
              Text('Response:\n$_response'),
            ],
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    _tcpTunnel?.close();
    _controller.dispose();
    super.dispose();
  }
}

代码解释:

  1. 依赖添加:在 pubspec.yaml 文件中添加 tcp_tunnel 依赖。
  2. 初始化TCP连接:在 initState 方法中初始化 TcpTunnel 对象,并连接到指定的服务器地址和端口。
  3. 数据监听:通过 _tcpTunnel!.dataStream.listen 监听从服务器接收到的数据,并更新UI。
  4. 发送消息:在 _sendMessage 方法中,将用户输入的消息发送到服务器。
  5. UI界面:使用 TextFieldElevatedButton 创建一个简单的UI,用户可以输入消息并发送。
  6. 清理资源:在 dispose 方法中关闭TCP连接并释放资源。

请注意,tcp_tunnel 插件的具体用法可能会随着版本更新而有所变化,因此请查阅最新的文档和示例代码以确保兼容性。

回到顶部