Skip to main content

SERVER/CLIENT cannot send and recieve data on the same socket, server close server after first attempt

Hi im trying to create a backup function for my program, the idea is to copy and send all the files from one especific folder from my client to the server, the issue here is everytime i send the file name and size of every file as a list the server close the conecction after its recieve but i need the server to ask the client for the data of the files itself, the main is like follows

make a list of all files on folder -------> send the list of Files and size via sockets ------> recieve and ask back the file i want to copy one by one ----->send the data of the actual file -----> repeat until the list is over

it supose i handle the data send using the ready read signal but for some reason i cant send the actual data, the conecction is closed, this is a good way on handling the data? or its better to send all data at once? like filename + <SEP> + datafile theres any way to split the data recive without messing the data of the file???

i add my actual code, the client is in C++ and the server is in python, any help is welcome

Server.py

def servidorMk3():
    host = socket.gethostname()
    host_port = 8000
    host_ip = socket.gethostbyname(host)
    buffer = 1024
    cnt = 0
    code_end = "<END>"
    code_ok = "<OK>"
    code_fin = "<FIN>"
    code_bad = "<BAD>"
    nombre = []
    tamano = []
    
    print (f"Servidor Mk3")
    print (f"Ip del servidor: " + host_ip)
    log("Inicio del servidorMk3 " + host_ip)
    
    # while True:
    #     send_UDP_broadcast(host_ip)
    #     ip = lisent_UDP_broadcast()
    #     if ip:
    #         break
    #     else:
    #         continue
    
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) as tcp_conn:
        tcp_conn.bind((host_ip, host_port))
        tcp_conn.listen(2)
        con, adrs = tcp_conn.accept()
        with con:
            cnt += 1
            print (f"Conecion Exitosa")
            log("Connecion exitosa con el server: " + adrs[0])
            if cnt > 20:
                log("Fin del ciclo")
            else:
                while True:
                    # start to recieve the list of files
                    while True:         # start to fill the socket
                        data = con.recv(buffer)
                        if not data:     # if theres no data close the loop
                            break
                        if code_end.encode("utf8") in data:  # if found <END>, ends the current element
                            break
                    data = data.decode("utf8")
                    elemt = []
                    elemt = data.split("<SEPARATOR>")
                    if code_fin in data:  # if found <FIN>, the list is over
                         break     
                    
                    ##  Erease the empty elements
                    ##  **************************************************
                    if code_end in elemt: elemt.remove(code_end)
                    #print("antes de borrar elementos")
                    #for a in range(len(elemt)):
                    #    print(elemt[a])
                    elemt = list(filter(None, elemt))
                    print ("despues de borrar")
                    for a in range(len(elemt)):
                        print(elemt[a])
                    if not elemt:
                        nombre, tamano = elemt[:2]
                    else:
                    #    print("Elemento vacio")
                        break
                    ## **************************************************
                    
                    #  now i ask what file i want to recieve
                    #request_files(nombres, adrs, host_port)
                # creates 2 independent list then iterate and asign names and size respectively
                
                for a in range (len(nombre)):
                   # here i ask the names and start asking the client for it
                    con.send(nombre[a].encode("utf8"))
                    print (nombre[a])
                    while True:    # recive the data file
                        file_data = con.recv(buffer)      
                        if not file_data:
                            break
                    #     # revisar como comparar el tamaño que ya tengo vs el tamaño que recibo
                    #     #https://stackoverflow.com/questions/449560/how-do-i-determine-the-size-of-an-object-in-python
                    #     if int(nombres[1]) == sys.getsizeof(file_data):
                    #         break
                    
                    # # Here i save the files to disk
                    directorio = crear_directorio()
                    if directorio == "<BAD>":
                        print(" no se puede crear la ubicacion")
                        print(type(directorio))  # revisar el tipo que regresa esta funcion¡¡¡¡
                        print(directorio)
                    else:
                        file_name = directorio + nombre[a]  # path to the file,   
                        file_size = int(tamano[a])   # size of file
                        file_create = open(file_name, 'wb')  # open file for writing in binary 
                        while (file_data):   # creacion y escritura del archivo
                            file_create.write(file_data)   # writes to the file
                        file_create.close()     #close the file
                        check = os.path.getsize(file_name)  # returns the size of the file
                    
                        if check == file_size:
                            #con.send(code_ok.encode())
                            log("archivo " + nombre[a] + " creado, tamaño: " + tamano[a])
                        else:
                            #con.sendall(code_bad.encode())
                            log("No se pudo crear el archivo: " + nombre[a])
            
            log("Respaldo de Archivos completado")
            print(f"Respaldo de archivos terminada")

client.c++

Server::Server() {    // server constructor
     Gen gen;  // Logs 

     QObject::connect(TCP_socket, &QTcpSocket::readyRead,  [&]() {  //  the idea is to handle here the data of the file
            QString dataread;
            gen.Log
            QByteArray data, block_file;
            QDataStream salida(TCP_Socket);
            QStringList File_Name;
            QDir directorio("Data/");
            bool yes;

            File_Name = directorio.entryList (QStringList() << "*.db" << "*.DB" << "*.Db" << "*.dB" , QDir::Files  );
            data = TCP_socket->readAll();
            dataread.append(data);

            foreach (QString lista, File_Name) {
                     block_file.clear();
                     if (lista == dataread) {
                         QFile Archivo("Data/" + lista);
                         Archivo.open(QIODevice::ReadOnly);
                         block_file = Archivo.readAll();
                         gen.Log(Lista);
                      }
                    if (TCP_socket->isValid() ) {
                          gen.Log("antes de escribir");
                          salida.writeRawData ( (char*)(block_file.data()), block_file.size() );                    
                          yes = TCP_socket->flush();
                          TCP_socket->waitForBytesWritten();
                          yes == true ? gen.Log("Datos Enviados: " + lista) : gen.Log("No se envio la data del archivo: " + lista);
                      }
               }
      });


void Server::TCP_Request_Send() {     // actual backup function
      Gen L; 
      QString Ip ("192.168.1.123");     // need to add a broadcast function to retrieve the ip
       qint64 filesize;
       bool yes = false;
       QByteArray block, block_file; 
      QStringList File_name;
       QDir directorio("Data/");

       File_Name = directorio.entryList (QStringList() << "*.db" << "*.DB" << "*.Db"<< "*.db", QDir::Files );
       File_Name.append ("<FIN>");
       L.Log ("..........Lista de Archivos");

       if (TCP_socket->state() == QAbstractSocket::UnconnectedState ) {
               L.Log("Before connection");
               TCP_socket->connectToHost( Ip, 8000, QIODevice::WriteOnly);
               if (TCP_socket->waitForConnected(5000) ) {
                       QDataStream salida(TCP_socket);
                       foreach ( QString files, File_Name) {
                             QFile Archivo ("Data/" + files);
                             std::string nombre = files.toStdString();
                             L.Log (QString::fromStdString(nombre) );
                             Archivo.open (QIODevice::ReadOnly);
                             block_file = Archivo.readAll();
                             filesize = Archivo.size();
                             block.clear();
                         
                             if (files == "<FIN>") {
                                    block.append ("<FIN><SEPARATOR><END>");
                             } else {
                                    block.append (QString::fromStdString(nombre) + "<SEPARATOR>"  + QString::number(filesize) + "<SEPARATOR>" + "<END>" );
                                    if (block.isEmpty() == true) {
                                             continue;    // if empty the for continues
                                        }
                             }

                           L.Log ("despues de block");
                           if (TCP_socket->isValid() ) {
                                 L.Log ("antes de escribir");
                                 salida.writeRawData ( (char*)(block.data()), block.size() );
                                 yes = TCP_socket->waitForBytesWritten();
                                L.Log (QString::fromUtf8(block.constData(), block.size()  ) );
                                yes == true ? L.Log ("nombre " + files + " enviado") : L.Log ("no se pudo enviar el nombre" + files );
                          }
               Archivo.close();
          };
       }
     }
  }

EDIT: I did follow Tims Roberts advice and get rid of the while true and also sending all the info and data from each file all at once it works, but for some reason the data is not reaching correctlly, i should recive the first elemnt but i recieve the second and the list start from there.

i should get something like this

Conecion Exitosa
despues de borrar
0 ..  Ciclo_OI.db
1 ..  25698
Tamaño esperado: 25698 ... tamaño real: 25698

despues de borrar
0 .. Ciclo_OI_2020_2021.db
1 .. 32768
Tamaño esperado: 32768 ... tamaño real 32768

but i get this instead, that of course is totally wrong

Conecion Exitosa
despues de borrar
0 .. <END>Ciclo_OI_2020_2021.db
1 .. 32768
Tamaño esperado: 32768 ... tamaño real 324 

despues de borrar
0 .. <END>Ciclo_PV_2020_2021.db
1 .. 32768
Tamaño esperado: 32768 ... tamaño real 66 

my current code is as follows

with socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) as tcp_conn:
    tcp_conn.bind((host_ip, host_port))
    tcp_conn.listen(1)
    con, adrs = tcp_conn.accept()
    print (f"Conecion Exitosa")
    log("Connecion exitosa con el server: " + adrs[0])
    
    while True:
        #empieza a recibir la lista de los archivos
        while True:         # recibe la info en general
            data = con.recv(buffer)
            if not data:     # si no hay informacion se cierra el ciclo
                break
            if code_end.encode("utf8") in data:  # si llega <END>, termino el elemento actual
                break
        
        if code_fin.encode("utf8") in data:  # si llega <FIN>, se acabo la lista
            break     
        elemt = []
        elemt = data.split(b'<SEP>')

        
        ##  Elimina los elementos vacios
        ##  **************************************************
        
        # for a in range(len(elemt)):
        #     if code_end.encode("utf8") in elemt[a]:
        #         elemt[a] = elemt[a].strip(b'<END>')
                # elemt[a] = elemt[a].remove(code_end.encode("utf8"))
        #print("antes de borrar elementos")
        #elemt = list(filter(None, elemt))   # erase empty spaces
        if len(elemt) < 3:
            nombre = elemt[0].decode("utf8")
            print(nombre)
            size = elemt[1].decode("utf8")
            dataFile =  elemt[2]
            print (f" menor a {len(elemt)}")
        if len(elemt) > 3:
            nombre = elemt[1].decode("utf8")
            size = elemt[2].decode("utf8")
            dataFile =  elemt[3]
            print (f" mayor a {len(elemt)}")
        #for a in range(len(elemt)):  # remove <END>
        #    if code_end.encode("utf8") in elemt[a]:
        nombre.replace("<END>","")     # get rid of end
        nombre = nombre.strip()   # erase empty spaces
        size = size.strip()
        #size = list(filter(None, size))
        
        # there should be 3 elemnts now name, size, datafile
        print ("despues de borrar")
        #for a in range(len(elemt)):
        #    print(elemt[a].decode("utf8"))
        # if not elemt:
        #     nombre, tamano = elemt[:2]
        # else:
        # #    print("Elemento vacio")
        #     break
        ## **************************************************
        
        #  ahora ahy que pedir cual archivo nos mande
        #request_files(nombres, adrs, host_port)
    
    # crear 2 listas independientes y luego iterarlas, asignarles los nombres y tamanos respectivamente
    # for a in range (len(nombre)):
    #     #  aqui tomar los nombres y pedirlos    
    #     #con.send(nombre[a].encode("utf8"))
    #     print (nombre[a])
    #     while True:    # recibe la data del archivo
    #         file_data = con.recv(buffer)      
    #         if not file_data:
    #             break
        #     # revisar como comparar el tamaño que ya tengo vs el tamaño que recibo
        #     #https://stackoverflow.com/questions/449560/how-do-i-determine-the-size-of-an-object-in-python
        #     if int(nombres[1]) == sys.getsizeof(file_data):
        #         break
        
        # # Aqui guardo los archivos a disco revisar la funcion mk2
        directorio = crear_directorio()
        if directorio == "<BAD>":
            print(" no se puede crear la ubicacion")
            print(type(directorio))  # revisar el tipo que regresa esta funcion¡¡¡¡
            print(directorio)
        else:
            print(f"0 .. {nombre}")
            print(f"1 .. {size}")
            #print (dataFile)
            file_name = directorio + nombre  # path to the file,   
            file_size = int(size)   # size of file
            
                   # actual data of the file
            file_create = open(file_name, 'wb')  # open file for writing in binary 
            #while (dataFile):   # creacion y escritura del archivo
            file_create.write(dataFile)   # writes to the file
            file_create.close()     #close the file
            check = os.path.getsize(file_name)  # returns the size of the file
            print (f"Tamaño esperado: {file_size} ... tamaño real {check} ")
            
            if check == file_size:
                #con.send(code_ok.encode())
                log("archivo " + file_name + " creado, tamaño: " + file_size)
            else:
                #con.sendall(code_bad.encode())
                log("No se pudo crear el archivo: " + file_name)
    
    log("Respaldo de Archivos completado")
    print(f"Respaldo de archivos terminada")


source https://stackoverflow.com/questions/71945497/server-client-cannot-send-and-recieve-data-on-the-same-socket-server-close-serv

Comments

Popular posts from this blog

How to show number of registered users in Laravel based on usertype?

i'm trying to display data from the database in the admin dashboard i used this: <?php use Illuminate\Support\Facades\DB; $users = DB::table('users')->count(); echo $users; ?> and i have successfully get the correct data from the database but what if i want to display a specific data for example in this user table there is "usertype" that specify if the user is normal user or admin i want to user the same code above but to display a specific usertype i tried this: <?php use Illuminate\Support\Facades\DB; $users = DB::table('users')->count()->WHERE usertype =admin; echo $users; ?> but it didn't work, what am i doing wrong? source https://stackoverflow.com/questions/68199726/how-to-show-number-of-registered-users-in-laravel-based-on-usertype

Why is my reports service not connecting?

I am trying to pull some data from a Postgres database using Node.js and node-postures but I can't figure out why my service isn't connecting. my routes/index.js file: const express = require('express'); const router = express.Router(); const ordersCountController = require('../controllers/ordersCountController'); const ordersController = require('../controllers/ordersController'); const weeklyReportsController = require('../controllers/weeklyReportsController'); router.get('/orders_count', ordersCountController); router.get('/orders', ordersController); router.get('/weekly_reports', weeklyReportsController); module.exports = router; My controllers/weeklyReportsController.js file: const weeklyReportsService = require('../services/weeklyReportsService'); const weeklyReportsController = async (req, res) => { try { const data = await weeklyReportsService; res.json({data}) console...

How to split a rinex file if I need 24 hours data

Trying to divide rinex file using the command gfzrnx but getting this error. While doing that getting this error msg 'gfzrnx' is not recognized as an internal or external command Trying to split rinex file using the command gfzrnx. also install'gfzrnx'. my doubt is I need to run this program in 'gfzrnx' or in 'cmdprompt'. I am expecting a rinex file with 24 hrs or 1 day data.I Have 48 hrs data in RINEX format. Please help me to solve this issue. source https://stackoverflow.com/questions/75385367/how-to-split-a-rinex-file-if-i-need-24-hours-data