Flutter app can send to UDP server in docker container but cannot receive data sent from server. This means that in a Flutter application, you can use the UDP protocol to send data to a server running in a docker container. However, when the server tries to send data to the application, the Flutter application cannot receive the data. This may cause limitations in some specific application scenarios, so you need to pay attention to this when developing Flutter applications.
I am currently developing a backend udp service in go that communicates with a flutter mobile app.
This is the udp service code:
package main import ( "log" "net" "os" "time" ) func main() { port := ":8080" logger := log.new(os.stdout, "", log.ldate|log.ltime) udp_server, err := net.resolveudpaddr("udp4", port) if err != nil { logger.fatalln(err.error()) return } udp_connection, err := net.listenudp("udp4", udp_server) if err != nil { logger.fatalln(err.error()) return } defer udp_connection.close() buffer := make([]byte, 1024) for { n, addr, err := udp_connection.readfromudp(buffer) if err != nil { udp_connection.writetoudp([]byte("error reading from udp connection"), addr) } buffer_string := string(buffer[0:n]) time_sent := time.now() time_sent_string := time_sent.string() combined_string := buffer_string + time_sent_string data := []byte(combined_string); logger.println(combined_string); _, err = udp_connection.writetoudp(data, addr) if err != nil { logger.fatalln(err.error()) return } } }
So far, the service runs using docker and can receive data sent from the flutter application, but the application cannot receive data sent back by the server.
The following are flutter code snippets for receiving and sending messages:
final socket = await rawdatagramsocket.bind(internetaddress.anyipv4, 0).onerror((error, stacktrace) => throw error assocketexception); final server = internetaddress("10.0.2.2"); final port = 8080; final data = [ deviceinfodata.deviceid, datetime.now().toutc().tostring() ]; datetime current = datetime.now(); late datetime responsetime; socket.send(data.tostring().codeunits, server, port); string serverout = ""; socket.listen((event) { final datagram = socket.receive(); if (datagram != null) { // print("data sent to server: ${datagram.data}"); string message = string.fromcharcodes(datagram.data); serverout = message.split("]").last; log(message); socket.close(); } else { socket.close(); } });
The dockerfile of udp service is:
# Specifies a parent image FROM golang:1.19.2-bullseye # Creates an app directory to hold your app’s source code WORKDIR /app # Copies everything from your root directory into /app COPY . . # Installs Go dependencies RUN go mod download # Builds your app with optional configuration RUN go build -o /udp-go # Tells Docker which network port your container listens on EXPOSE 8080 # Specifies the executable command that runs when the container starts CMD [ "/udp-go" ]
To run it, I use the following command:
docker build --rm -t udp-go:alpha .
docker run -d -p 8080:8080/udp --name go-udp udp-go:alpha
I use /udp
to map the udp port in the container to port 8080 on the docker host (https://docs.docker.com/config/containers/container-networking/)
However, this only allows me to send data to the service. I know this because checking the docker logs shows that the service is actually receiving data. If I were to run the service using plain old go run
instead of using docker, the application could send and receive messages. How can I solve this problem?
Edit: I tried adding expose 8080\udp
to the dockerfile instead of just expose 8080
but it still has the same error.
It turns out that the problem here lies in the flutter code itself. The code snippet below is a valid code snippet.
final socket = await RawDatagramSocket.bind(InternetAddress.anyIPv4, 0).onError((error, stackTrace) => throw error asSocketException); final server = InternetAddress("10.0.2.2"); final port = 8080; final data = [ deviceInfoData.deviceId, DateTime.now().toUtc().toString() ]; DateTime current = DateTime.now(); late DateTime responseTime; socket.send(data.toString().codeUnits, server, port); String serverOut = ""; socket.listen((event) { final datagram = socket.receive(); if (datagram != null) { // print("Data sent to server: ${datagram.data}"); String message = String.fromCharCodes(datagram.data); serverOut = message.split("]").last; log(message); } }, onDone: () => socket.close(), );
When using udp code, we have to close the socket on ondone
instead of closing the socket while listening, because dart may not have fully received the packet.
The above is the detailed content of Flutter app can send to UDP server in docker container but cannot receive data sent from server. For more information, please follow other related articles on the PHP Chinese website!