Flutter SOCKS代理插件socks_socket的使用

Flutter SOCKS代理插件socks_socket的使用

SOCKS sockets

Pub GitHub

SOCKS版本5的套接字,例如通过套接字连接到ElectrumX和/或Fulcrum服务器。

特性

  • 支持Dart & Flutter 3。
  • 支持SOCKS版本5协议。
  • 支持通过套接字连接到ElectrumX和Fulcrum服务器。
  • 异步支持,用于非阻塞网络通信。
  • 轻量级且依赖少。

开始使用

查看socks_socket.dart文件以获取属性和方法,并参考示例。

import 'package:socks_socket/socks_socket.dart';

// 在本地主机上实例化一个socks套接字,并选择由tor服务选定的端口。
var socksSocket = await SOCKSSocket.create(
    proxyHost: InternetAddress.loopbackIPv4.address,
    proxyPort: Tor.instance.port,
    sslEnabled: true, // 对于SSL连接。
);

// 连接到上面实例化的socks套接字。
await socksSocket.connect();

// 通过socks套接字连接到bitcoin.stackwallet.com的50002端口。
//
// 注意这是一个SSL示例。
await socksSocket.connectTo('bitcoin.stackwallet.com', 50002);

// 向套接字发送服务器功能命令,参见方法获取更多具体用法示例。
await socksSocket.sendServerFeaturesCommand();

完整示例

以下是一个完整的示例应用,展示了如何使用socks_socket插件来通过Tor访问比特币服务器。

// 示例应用依赖项,不一定是使用Tor所必需的。
import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:socks_socket/socks_socket.dart';
// 需要导入的Tor依赖项:
import 'package:socks5_proxy/socks_client.dart'; // 仅用于示例;可以使用任何socks5代理包,选择你喜欢的。
import 'package:tor_ffi_plugin/tor_ffi_plugin.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Home(),
    );
  }
}

class Home extends StatefulWidget {
  const Home({super.key});

  [@override](/user/override)
  State<Home> createState() => _MyAppState();
}

class _MyAppState extends State<Home> {
  // 标记Tor是否已启动。
  bool torIsRunning = false;

  // 设置主机输入字段的默认文本。
  final hostController = TextEditingController(text: 'https://icanhazip.com/');
  // https://check.torproject.org 是另一个好的选项。

  Future<void> startTor() async {
    // 启动Tor守护进程。
    await Tor.instance.start(
      torDataDirPath: (await getApplicationSupportDirectory()).path,
    );

    // 更新标记。
    setState(() {
      torIsRunning = Tor.instance.status == TorStatus.on;
    });

    print('等待结束;Tor应该正在运行');
  }

  [@override](/user/override)
  void dispose() {
    // 当小部件被销毁时清理控制器。
    hostController.dispose();
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    const spacerSmall = SizedBox(height: 10);
    return Scaffold(
      appBar: AppBar(
        title: const Text('Tor示例'),
      ),
      body: SingleChildScrollView(
        child: Container(
          padding: const EdgeInsets.all(10),
          child: Column(
            children: [
              TextButton(
                onPressed: torIsRunning
                    ? null
                    : () async {
                        unawaited(
                          showDialog(
                            barrierDismissible: false,
                            context: context,
                            builder: (_) => const Dialog(
                              child: Padding(
                                padding: EdgeInsets.all(20.0),
                                child: Text("启动Tor..."),
                              ),
                            ),
                          ),
                        );

                        final time = DateTime.now();

                        print("当前时间: $time");

                        await startTor();

                        print("启动Tor耗时 "
                            "${DateTime.now().difference(time).inSeconds} "
                            "秒");

                        if (mounted) {
                          Navigator.of(context).pop();
                        }
                      },
                child: const Text("启动Tor"),
              ),
              Row(
                children: [
                  // 主机输入字段。
                  Expanded(
                    child: TextField(
                      controller: hostController,
                      decoration: const InputDecoration(
                        border: OutlineInputBorder(),
                        hintText: '请求的主机',
                      ),
                    ),
                  ),
                  spacerSmall,
                  TextButton(
                    onPressed: torIsRunning
                        ? () async {
                            // `socks5_proxy` 包示例,使用另一个socks5
                            // 连接,选择你自己的。
                            
                            // 创建HttpClient对象
                            final client = HttpClient();

                            // 分配连接工厂。
                            SocksTCPClient.assignToHttpClient(client, [
                              ProxySettings(InternetAddress.loopbackIPv4,
                                  Tor.instance.port,
                                  password: null), // TODO 需要从Tor配置文件中获取。
                            ]);

                            // GET 请求。
                            final request = await client
                                .getUrl(Uri.parse(hostController.text));
                            final response = await request.close();

                            // 打印响应。
                            var responseString = await utf8.decodeStream(response);
                            print(responseString);
                            // 如果主机输入字段保持为默认的icanhazip.com,则应打印出Tor出口节点的IP地址。
                            //
                            // https://check.torproject.org 也适用于检查Tor连接状态。

                            // 关闭客户端
                            client.close();
                          }
                        : null,
                    child: const Text("发起代理请求"),
                  ),
                ],
              ),
              spacerSmall,
              TextButton(
                onPressed: torIsRunning
                    ? () async {
                        // 在本地主机上实例化一个socks套接字,并选择由tor服务选定的端口。
                        var socksSocket = await SOCKSSocket.create(
                          proxyHost: InternetAddress.loopbackIPv4.address,
                          proxyPort: Tor.instance.port,
                          sslEnabled: true, // 对于SSL连接。
                        );

                        // 连接到上面实例化的socks套接字。
                        await socksSocket.connect();

                        // 通过socks套接字连接到bitcoin.stackwallet.com的50002端口。
                        //
                        // 注意这是一个SSL示例。
                        await socksSocket.connectTo(
                            'bitcoin.stackwallet.com', 50002);

                        // 向连接的套接字发送服务器功能命令,参见方法获取更多具体用法示例。
                        await socksSocket.sendServerFeaturesCommand();

                        // 你应该在控制台看到服务器响应。
                        //
                        // 示例响应:
                        // `flutter: secure responseData: {
                        // 	"id": "0",
                        // 	"jsonrpc": "2.0",
                        // 	"result": {
                        // 		"cashtokens": true,
                        // 		"dsproof": true,
                        // 		"genesis_hash": "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
                        // 		"hash_function": "sha256",
                        // 		"hosts": {
                        // 			"bitcoin.stackwallet.com": {
                        // 				"ssl_port": 50002,
                        // 				"tcp_port": 50001,
                        // 				"ws_port": 50003,
                        // 				"wss_port": 50004
                        // 			}
                        // 		},
                        // 		"protocol_max": "1.5",
                        // 		"protocol_min": "1.4",
                        // 		"pruning": null,
                        // 		"server_version": "Fulcrum 1.9.1"
                        // 	}
                        // }

                        // 关闭套接字。
                        await socksSocket.close();
                      }
                    : null,
                child: const Text(
                  "通过socks套接字连接到bitcoin.stackwallet.com:50002 (SSL)",
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

更多关于Flutter SOCKS代理插件socks_socket的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

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


当然,下面是一个关于如何在Flutter项目中使用socks_socket插件来实现SOCKS代理的示例代码。这个插件允许你通过SOCKS代理进行网络请求。

首先,确保你已经在pubspec.yaml文件中添加了socks_socket依赖:

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

然后运行flutter pub get来安装依赖。

接下来,我们编写一个简单的Flutter应用,演示如何使用socks_socket插件来通过SOCKS代理发送HTTP请求。

main.dart

import 'package:flutter/material.dart';
import 'package:socks_socket/socks_socket.dart';
import 'dart:io';
import 'dart:convert';

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

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

class _MyAppState extends State<MyApp> {
  String _response = "";

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('SOCKS Proxy Example'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text('Response:'),
              Text(_response, style: TextStyle(fontSize: 20)),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: _sendRequest,
                child: Text('Send Request'),
              ),
            ],
          ),
        ),
      ),
    );
  }

  Future<void> _sendRequest() async {
    // SOCKS代理配置
    String socksHost = 'your.socks.proxy.host';
    int socksPort = 1080; // SOCKS代理端口
    String socksUsername = 'your_username'; // 如果代理需要认证
    String socksPassword = 'your_password'; // 如果代理需要认证

    // 目标URL
    String targetUrl = 'http://httpbin.org/get';

    // 创建SOCKS客户端
    SocksSocketClient socksClient = SocksSocketClient(
      socksHost,
      socksPort,
      username: socksUsername,
      password: socksPassword,
    );

    try {
      // 连接到目标URL
      HttpClient client = HttpClient()
        ..badCertificateCallback =
            ((X509Certificate cert, String host, int port) => true); // 忽略SSL证书验证(仅用于测试)

      HttpClientRequest request = await client.openUrl('GET', Uri.parse(targetUrl));

      // 使用SOCKS代理发送请求
      HttpClientResponse response = await socksClient.send(request);

      // 读取响应
      String responseBody = await utf8.decodeStream(response);

      // 更新UI
      setState(() {
        _response = responseBody;
      });

      // 关闭连接
      await response.close();
      await client.close();
    } catch (e) {
      // 处理异常
      setState(() {
        _response = 'Error: $e';
      });
    } finally {
      // 关闭SOCKS客户端
      socksClient.close();
    }
  }
}

注意事项

  1. 代理配置:请替换socksHostsocksPortsocksUsernamesocksPassword为你的SOCKS代理服务器的实际配置。
  2. 忽略SSL证书验证badCertificateCallback用于忽略SSL证书验证,仅适用于测试环境。在生产环境中,你应该正确验证SSL证书。
  3. UI更新:在Flutter中,所有UI更新都应该在setState方法中进行,以确保界面正确刷新。

运行应用

确保你的开发环境已经配置好Flutter,然后运行flutter run来启动应用。点击“Send Request”按钮,你应该能看到通过SOCKS代理发送HTTP请求后的响应内容。

这个示例代码展示了如何在Flutter应用中使用socks_socket插件来配置和使用SOCKS代理。希望这对你有所帮助!

回到顶部