I'm currently implementing a tcp socket connection in my flutter app that runs in the background and fetches data for the app to display.
Establishing the connection works fine and i also receive the initial message from my server, however, after the first message is received the onDone
is called from my socket.listen()
and the stream closes down.
For the right implementation i need to keep the stream alive and exchange multiple messages. Actually the plan is to keep the socket alive all the time while the app is running in the foreground.
Server-side cannot be a problem as i implemented the same client on C# before (i've been simply looping stream.Read()
all the time without a problem).
Here's how my function looks right now:
_socket = await SecureSocket.connect(_ipAddressServer, _portServer,
onBadCertificate: (X509Certificate c) {
print("Certificate WARNING: ${c.issuer}:${c.subject}");
isSocketConnected = true;
return true;
}).catchError((error, stackTrace) async {
return false;
}).timeout(const Duration(seconds: 5));
print("Connected!");
_socket.setOption(SocketOption.tcpNoDelay, true);
_socket.listen((message) {
_handleSocketMessage(message);
}).onDone(() {
print("Socket done");
});
As i said, after the first message is received, the onDone
is called immediately and i don't receive any more messages from the socket. It is obgliated for the functionality to keep the connection alive with the server.
Any suggestions?
EDIT:
Maybe the problem is somewhere else. Inside the _handleSocketMessage(message)
i'm actually calling the _socket.write(data)
again. Is that the wrong approach? Should i rather call the _handleSocketMessage(message)
inside an isolate? I'm still trying to get the hang of multi-threading in dart, that part was a bit easier in C# not gonna lie.
CodePudding user response:
I don't see any problem with your code here. I noticed though that you are calling onDone
on the (message) {...}
function, while I think you want to use the onDone
argument of _socket.listen()
. When your code runs, the socket is still open after printing "Socket done", if I am correct.
What I think you're looking for is this:
_socket.listen(
(message) {
_handleSocketMessage(message);
},
onDone: () {
print('Socked done');
},
);
CodePudding user response:
The issue wasn't with my listen method. It was actually my _socket.write()
that screwed things up.
My server expects me to send a raw byte array (in Dart terms Uint8List
). Coming from c# i thought the _socket.write()
would be practially the same as in a .NET c# socket, but it actually sends a String to the socket from whatever you pass into it. So my Uint8List
got converted to a String and my Server had no idea how to handle it.
I swapped out _socket.write(payload)
with _socket.add(payload)
and everything works fine.