client_server_lan 1.1.0

  • Readme
  • Changelog
  • Example
  • Installing
  • 63

client_server_lan #

Pub Documentation

A LAN communication Flutter package based off Node Commander but removing parts such as Commander Nodes and making communication between client and server two way.

Usage #

Run a Node #

Start a Server Node

import 'dart:async';
import 'package:wifi/wifi.dart';
import 'package:client_server_lan/client_server_lan.dart';
void startServer() async {
    String ip = await Wifi.ip;
    server = ServerNode(
      name: "Server",
      verbose: true,
      host: ip,
      port: 8085,
    );
    await server.init();
    await server.onReady;
    setState(() {
      serverStatus = "Server ready on ${server.host}:${server.port}";
    });
    server.dataResponse.listen((DataPacket data) {
      setState(() {
        dataRecieved = data.payload;
      });
    });
  }

Start a Client Node

void startClient() async {
    dropdownEnabled = false;
    String ip = await Wifi.ip;
    client = ClientNode(
      name: "Client Node",
      verbose: true,
      host: ip,
      port: 8085,
    );
    await client.init();
    await client.onReady;
    setState(() {
      clientStatus = "Client ready on ${client.host}:${client.port}";
    });
    client.dataResponse.listen((DataPacket data) {
      setState(() {
        dataRecieved = data.payload;
      });
    });
  }

Server scan for Clients

void findClients() async {
    server.discoverNodes();
    await Future<dynamic>.delayed(const Duration(seconds: 2));
    clientIPs = "";
    for (final s in server.clientsConnected) {
      setState(() {
        clientIPs += "id=${s.name},IP=${s.address}\n";
      });
    }
  }

Transfer Data #

Transfer from Client to Server

void clientToServer() async {
    await client.sendData("userInfo",dataToSend, client.serverDetails.address);
  }

Transfer from Server to Client

void serverToClient(String clientName) async {
    final String client = server.clientUri(clientName);
    await server.sendData("userInfo",dataToSend, client);
  }

[1.1.0] - 30/04/2020 #

  • Remove access to internal API components to make API simpler
  • Added a shield.io so easy to find auto generated documentation and the pub.dev package

[1.0.2] - 30/04/2020 #

  • Code cleanup and addition to documentation

[1.0.1] - 21/04/2020 #

  • Minor changes to code formatting

[1.0.0] - 21/04/2020 #

  • I did a massive overhaul so that the data transferred is a packet object rather then just a string. This allows the information of each packet to be read (e.g host, port, name of user packet from). On top of this you can also give packets names. This means you can send mutliple types of data as a payload (be wary that the data may be converted into String upon arrival).
  • Feel free to leave feedback (or even contribute 😁 )on my Github as this is still a work in progress.

[0.1.1] - 20/04/2020 #

  • The package now has a reasonable length description.

[0.1.0] - 20/04/2020 #

  • The package has been created. It's still going to be unstable as many of the features haven't yet been tested.
  • Thank the creator of Node Commander as he is the real one behind all this

example/lib/main.dart

import 'package:flutter/material.dart';
import 'dart:async';
import 'package:wifi/wifi.dart';
import 'package:client_server_lan/client_server_lan.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  ServerNode server;
  ClientNode client;
  bool dropdownEnabled = true;
  String serverStatus = "Server not running";
  String clientStatus = "Client not running";
  String clientIPs = "No devcies connected";
  String dataToSend = "Testing 1 2 3";
  String dataRecieved = "No response yet...";
  String clientToSend = "Moto g3 Client";
  String dropdownValue = "Server";

  void startServer() async {
    dropdownEnabled = false;
    String ip = await Wifi.ip;
    server = ServerNode(
      name: "Server",
      verbose: true,
      host: ip,
      port: 8085,
    );
    await server.init();
    await server.onReady;
    setState(() {
      serverStatus = "Server ready on ${server.host}:${server.port}";
    });
    server.dataResponse.listen((DataPacket data) {
      setState(() {
        dataRecieved = data.payload;
      });
    });
  }

  void startClient() async {
    dropdownEnabled = false;
    String ip = await Wifi.ip;
    client = ClientNode(
      name: "Client Node",
      verbose: true,
      host: ip,
      port: 8085,
    );
    await client.init();
    await client.onReady;
    setState(() {
      clientStatus = "Client ready on ${client.host}:${client.port}";
    });
    client.dataResponse.listen((DataPacket data) {
      setState(() {
        dataRecieved = data.payload;
      });
    });
  }

  void findClients() async {
    server.discoverNodes();
    await Future<dynamic>.delayed(const Duration(seconds: 2));
    clientIPs = "";
    for (final s in server.clientsConnected) {
      setState(() {
        clientIPs += "id=${s.name},IP=${s.address}\n";
      });
    }
  }

  void clientToServer() async {
    await client.sendData("userInfo", dataToSend, client.serverDetails.address);
  }

  void serverToClient(String clientName) async {
    final String client = server.clientUri(clientName);
    await server.sendData("userInfo", dataToSend, client);
  }

  void disposeClient() {
    client.dispose();
    setState(() {
      clientStatus = "Client not running";
    });
    dropdownEnabled = true;
  }

  void disposeServer() {
    server.dispose();
    setState(() {
      serverStatus = "Server not running";
    });
    dropdownEnabled = true;
  }

  @override
  void dispose() {
    dropdownEnabled
        ? dropdownValue == "Server" ? disposeServer() : disposeClient()
        : print("Disposing");
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: ListView(
          children: <Widget>[
            DropdownButton<String>(
              value: dropdownValue,
              icon: Icon(Icons.arrow_downward),
              iconSize: 24,
              elevation: 16,
              style: TextStyle(color: Colors.deepPurple),
              underline: Container(
                height: 2,
                color: Colors.deepPurpleAccent,
              ),
              onChanged: (String newValue) {
                if (dropdownEnabled) {
                  setState(() {
                    dropdownValue = newValue;
                  });
                }
              },
              items: <String>["Server", "Client"]
                  .map<DropdownMenuItem<String>>((String value) {
                return DropdownMenuItem<String>(
                  value: value,
                  child: Text(value),
                );
              }).toList(),
            ),
            dropdownValue == "Server"
                ? Column(
                    children: <Widget>[
                      Text(serverStatus),
                      RaisedButton(
                        child: Text("Start Server"),
                        onPressed: () => startServer(),
                      ),
                      RaisedButton(
                        child: Text("Scan Clients"),
                        onPressed: () => dropdownEnabled ? null : findClients(),
                      ),
                      Text(clientIPs),
                      TextField(
                        decoration: InputDecoration(
                            labelText: "Client to send data to",
                            border: InputBorder.none,
                            contentPadding: EdgeInsets.all(20)),
                        onChanged: (String text) {
                          setState(() {
                            clientToSend = text;
                          });
                        },
                      ),
                    ],
                  )
                : Column(
                    children: <Widget>[
                      Text(clientStatus),
                      RaisedButton(
                        child: Text("Start Client"),
                        onPressed: () => startClient(),
                      ),
                    ],
                  ),
            TextField(
              decoration: InputDecoration(
                  labelText: "Data to send",
                  border: InputBorder.none,
                  contentPadding: EdgeInsets.all(20)),
              onChanged: (String text) {
                setState(() {
                  dataToSend = text;
                });
              },
            ),
            RaisedButton(
              child: Text("Send Data"),
              onPressed: () => dropdownEnabled
                  ? null
                  : dropdownValue == "Server"
                      ? serverToClient(clientToSend)
                      : clientToServer(),
            ),
            Text(dataRecieved),
            RaisedButton(
              child: Text("Dispose $dropdownValue"),
              onPressed: () => dropdownEnabled
                  ? null
                  : dropdownValue == "Server"
                      ? disposeServer()
                      : disposeClient(),
            ),
          ],
        ),
      ),
    );
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  client_server_lan: ^1.1.0

2. Install it

You can install packages from the command line:

with pub:


$ pub get

with Flutter:


$ flutter pub get

Alternatively, your editor might support pub get or flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:client_server_lan/client_server_lan.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
26
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
63
Learn more about scoring.

We analyzed this package on Jul 12, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.8.4
  • pana: 0.13.15

Analysis suggestions

Package not compatible with runtime flutter-web on Web

Because:

  • package:client_server_lan/client_server_lan.dart that imports:
  • package:client_server_lan/src/basenode.dart that imports:
  • package:isohttpd/isohttpd.dart that imports:
  • package:isohttpd/src/utils.dart that imports:
  • package:body_parser/body_parser.dart that imports:
  • package:body_parser/src/parse_body.dart that imports:
  • package:http_server/http_server.dart that imports:
  • package:http_server/src/http_multipart_form_data.dart that imports:
  • package:http_server/src/http_multipart_form_data_impl.dart that imports:
  • dart:io

Package not compatible with runtime js

Because:

  • package:client_server_lan/client_server_lan.dart that imports:
  • package:client_server_lan/src/basenode.dart that imports:
  • package:isohttpd/isohttpd.dart that imports:
  • package:isohttpd/src/utils.dart that imports:
  • package:body_parser/body_parser.dart that imports:
  • package:body_parser/src/parse_body.dart that imports:
  • package:http_server/http_server.dart that imports:
  • package:http_server/src/http_multipart_form_data.dart that imports:
  • package:http_server/src/http_multipart_form_data_impl.dart that imports:
  • dart:io

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.7.0 <3.0.0
dio ^3.0.9 3.0.9
emodebug ^0.4.0 0.4.0
isohttpd ^0.4.0 0.4.0
meta ^1.1.8 1.2.2 1.3.0-nullsafety
Transitive dependencies
body_parser 1.1.1
charcode 1.1.3
collection 1.14.13 1.15.0-nullsafety
dart2_constant 1.0.2+dart2
extra_pedantic 1.2.0
http_parser 3.1.4
http_server 0.9.8+3
iso 0.3.0
mime 0.9.6+3
path 1.7.0
pedantic 1.9.2
source_span 1.7.0
string_scanner 1.0.5
term_glyph 1.1.0
typed_data 1.2.0 1.3.0-nullsafety