Search code examples
socketsflutterdartudpserversocket

Udp socket in Flutter does not receive anything


I'm trying to use a udp socket as server in Flutter. I'd like to bind this socket on my localhost at 6868 port always in listening. Unfortunately when i try to send something from a client,it never prints the string "RECEIVED". Here's the code:

static Future openPortUdp(Share share) async {
        await RawDatagramSocket.bind(InternetAddress.anyIPv4,6868)
        .then(
          (RawDatagramSocket udpSocket) {
            udpSocket.listen((e) {
              switch (e) {
                case RawSocketEvent.read:
                  print("RECEIVED");
                  print(String.fromCharCodes(udpSocket.receive().data));
                  break;
                case RawSocketEvent.readClosed:
                    print("READCLOSED");
                    break;
                case RawSocketEvent.closed:
                  print("CLOSED");
                  break;
              }
            });
          },
        );
      }

Am I doing something wrong?

Anyway this is the client side, it is written is Lua:

local udp1 = socket.udp()
while true do
    udp1:setpeername("192.168.1.24", 6868)
    udp1:send("HI")
    local data1 = udp1:receive()
    if (not data1 == nil) then print(data1) break end
    udp1:close()
end

I tested it with another server and it works well, so i don't think the client is the problem.

Thanks!


Solution

  • If it can help you, here my code for my SocketUDP (as singleton) in my app. I used it in localhost and it works very well :

    class SocketUDP {
      RawDatagramSocket _socket;
    
      // the port used by this socket
      int _port;
    
      // emit event when receive a new request. Emit the request
      StreamController<Request> _onRequestReceivedCtrl = StreamController<Request>.broadcast();
    
      // to give access of the Stream to listen when new request is received
      Stream<Request> get onRequestReceived => _onRequestReceivedCtrl.stream;
    
      // as singleton to maintain the connexion during the app life and be accessible everywhere
      static final SocketUDP _instance = SocketUDP._internal();
    
      factory SocketUDP() {
        return _instance;
      }
    
      SocketUDP._internal();
    
      void startSocket(int port) {
    
        _port = port;
    
        RawDatagramSocket.bind(InternetAddress.anyIPv4, _port)
            .then((RawDatagramSocket socket) {
          _socket = socket;
          // listen the request from server
          _socket.listen((e) {
            Datagram dg = _socket.receive();
            if (dg != null) {
              _onRequestReceivedCtrl.add(RequestConvert.decodeRequest(dg.data, dg.address));
            }
          });
        });
      }
    
      void send(Request requestToSend, {bool isBroadCast:false}) {
    
        _socket.broadcastEnabled = isBroadCast;
    
        final String requestEncoded = RequestConvert.encodeRequest(requestToSend);
         List<int> requestAsUTF8 = utf8.encode(requestEncoded);
        _socket.send(requestAsUTF8, requestToSend.address, _port);
      }
    }
    

    Edit : As asked below, here some details to use it.

    At first, the Request definition :

    import 'dart:io';
    import 'dart:typed_data';
    
    import 'package:remotepcmultitouch/enumRequest.dart';
    
    // describe a network request
    class Request
    {
      // the request ID
      final ERequest _id;
      // the request data list
      final List<String> _datas;
      // the request address (from/to)
      final InternetAddress _address;
      // binary data, optional
      final Uint8List binaryData;
    
      Request(this._id, this._datas, this._address, {this.binaryData});
    
      ERequest get id => _id;
      List<String> get datas => _datas;
      InternetAddress get address => _address;
    }
    

    To process a request received from the socket :

    SocketUDP().onRequestReceived.listen(onRequestReceived);
    
    void onRequestReceived(Request request) {
        switch (request.id) {
        // process the request
        }
    }
    

    To send a request with the SocketUDP : my example send touch position to server

    // send request to server to send the new touch data
    SocketUDP().send(Request(
        ERequest.SEND_TOUCH_DATA,
        [touchState.index.toString(), fingerID.toString(), percentX, percentY],
        this.address));
    

    Then RequestConvert.encodeRequest and RequestConvert.decodeRequest are just utility functions to convert/decode the Request object to/from string, nothing special (many ways to doing this)