Search code examples
pythonmultithreadingtcpserverclient

Problem with saving data from multiple Clients to one file. TCP Python


My main goal is to receive data from multiple clients to one txt file on my server. Everything is working great, clients connect to server, server recognize that they are diffrent clients, moreover, they are sending data to server (and it saves to data_r.txt file), however, they are overwriting the file. So I only gets data from the last client that sent the data. The name of file have to be the same for all clients. I have no idea what to do and how to fix it.

Server TCP

import socket
from threading import Thread
from socketserver import ThreadingMixIn

from threading import Thread
from socketserver import ThreadingMixIn

HOST = '192.168.0.108'
TCP_PORT = 60001
BUFFER_SIZE = 1024
class ClientThread(Thread):

   def __init__(self, ip, port, sock):
       Thread.__init__(self)
       self.ip = ip
       self.port = port
       self.sock = sock

   def run(self):
       filename = 'data_r.txt'
       f = open(filename, 'wb')
       while True:

          data = self.sock.recv(1024)
          if not data:
             f.close()
             #self.sock.close()
             break
          f.write(data)
    self.sock.sendall("File received")
    self.sock.close()


tcpsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('Creating socket...')
tcpsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
print('Socket created successfully')
print('Binding socket to the port...')
tcpsock.bind((HOST, TCP_PORT))
print(f'Socket binded successfully to port {TCP_PORT} ')
print('Waiting for clients to join....')

threads = []

while True:
   tcpsock.listen(5)
   (conn, (ip, port)) = tcpsock.accept()
   #conn.settimeout(7)
   newthread = ClientThread(ip, port, conn)
   print(newthread)
   newthread.start()
   threads.append(newthread)

for t in threads:
   t.join()

TCP Client

import socket

# TCP_IP = 'localhost'
HOST = '192.168.0.108'
TCP_PORT = 60001

BUFFER_SIZE = 1024

socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('Connecting to socket')
socket.connect((HOST, TCP_PORT))
print(f'Connected to host: {HOST}   on   port: {TCP_PORT}')

print('')
filename='data_s.txt'
f = open(filename, 'rb')

while True:
   chunk = f.read(BUFFER_SIZE)
   if not chunk:
      print ("File transfer completed")
      f.close()
      break
   socket.send(chunk)

c = socket.recv(BUFFER_SIZE)
print (c)
socket.close()
print('connection closed')

Solution

  • The first thing to correct is to use open(filename, 'ab') instead of 'wb' because you want to append to the file, not truncate it.

    Secondly, you have a race condition and, as the commenter has said, you should use something like a lock to synchronise access. Otherwise data will be lost sooner or later.