Different behaviour of Socket Class in Dart and Flutter

Viewed 656

i have two short Code Snippets which just serve for testing communication over a TCP Socket.

In Dart i have the following Code which compiles just fine and succesfully sends the Command to the esp8266 connected to my arduino:

import 'dart:io';

void main() async {
  Socket socket = await Socket.connect('192.168.2.123', 80);

  String command = "<2,1,>";
  socket.write(command);

  print(socket.port);

  await Future.delayed(Duration(seconds: 1));

  socket.close();
}

In Flutter the following snippet bound to a on Pressed Method does not succesfully sned the command:

class _MyStartScreenState extends State<MyStartScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
          child: FlatButton(
            color: Colors.orange,
            onPressed: _sendCommandToEsp,
            child: Text("On/Off"),
          )
      ),
    );
  }
  
  void _sendCommandToEsp() async{
    Socket socket = await Socket.connect('192.168.2.123', 80);
  
    String command = "<2,1,>";
    socket.write(command);
  
    await Future.delayed(Duration(seconds: 1));
  
    socket.close();
  }
  
}

Is there anything obvious I am not getting? I cannot figure out why this is the case. Help would be much appreciated!

2 Answers

If you read the documentation for close on Socket you will find the following note:

NOTE: Writes to the IOSink may be buffered, and may not be flushed by a call to close(). To flush all buffered writes, call flush() before calling close().

https://api.dart.dev/stable/dart-io/Socket/close.html

The reason for your current behavior where it seems to work on different platforms can be because of the different network stack in each OS and that Flutter can have a different implementation of the Socket class than when you are running in Dart VM.

However, your current code are dependent on undocumented behavior so it is best to use the flush() method and await the returned Future so you are sure the data are actually sent before running close() which will destroy any data in the buffer which has yet to be sent.

Okay, the Problem was that i used a port with a number smaller than 1024 which required root permisiion in most times. When I switched the Port to something higher, the Code began to work, but it still is seemingly random (at least i cant find a pattern), when the command gets received from the esp8266 and when it does not.

I will test this using a loop function with Delays.

Related