I am trying to send an image from a Flutter app to my TCP server written in Python. I have this tcp server code:
import socket
import os
# Server configuration
HOST = '192.168.1.67'
PORT = 8000
def save_image(data):
len_files = len([name for name in os.listdir('.') if os.path.isfile(name)])
filename = f'received_image-{len_files}.jpg'
with open(filename, 'wb') as f:
f.write(data)
print('Image saved to', filename)
# Create a TCP socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Bind the socket to the specified host and port
server_socket.bind((HOST, PORT))
# Listen for incoming connections (1 connection at a time)
server_socket.listen(1)
print('Server listening on', HOST, 'port', PORT)
# Wait for a client to connect
print('Waiting for a connection...')
client_socket, address = server_socket.accept()
print('Accepted connection from', address)
# Receive and save the images from the client
received_data = b''
while True:
try:
data = client_socket.recv(1024)
print('Receiving data...')
print('Length of data received:', len(data))
except Exception as e:
print('An error occurred while receiving data:', e)
break
if not data:
break
# Save the received data
received_data += data
print('Data received')
# Save the received image
save_image(received_data)
# Close the client connection
client_socket.close()
print('Connection closed')
Then, I send an image from my flutter app like this:
if (_socket == null) {
print("Socket not connected");
return;
}
print("Taking picture...");
final img = await _controller.takePicture();
print("Picture taken");
final imgBytes = await img.readAsBytes();
print("Sending image...");
_socket!.add(imgBytes);
print("Image sent");
Currently the expected result is the following:
However, at the moment, once the server receives an image, it starts logging receiving data and the length of the current chunk, but once it reaches the last chunk stops, and continues only when the connection is closed from the app side, which can either be done by closing the app, or adding the following line of code:
_socket!.close();
I could solve this by creating a new socket connection every time I want to send a picture and then handling every picture separately, however, I don't understand why it is not working the way I expect it to? Thanks in advance (I believe other parts of the Flutter code is not neccessary since the connection happens and I am able to send the pictures to the server)
... but once it reaches the last chunk stops
The server does not know that this is the last chunk. It only knows when it receives data and it knows when the connection is closed, i.e. not data
.
if not data:
break
Since it does not know when the image is done it can only wait until more data come in (which are assumed to belong to the same image) or the connection is closed.
If you want to send multiple images over the same TCP connection you need to implement an application protocol on top of TCP which allows to distinguish between multiple messages (the images) within the same byte stream. There are many questions here about this.