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
Post a Comment