send
Grupo de Telegram
play_arrow
Este sitio utiliza cookies propias y de terceros. Si continúa navegando consideramos que acepta el uso de cookies. OK Más Información.

Tutorial envio de archivos usando sockets

  • 4 Respuestas
  • 5540 Vistas

0 Usuarios y 3 Visitantes están viendo este tema.

Desconectado Once

  • *
  • Underc0der
  • Mensajes: 383
  • Actividad:
    0%
  • Reputación 0
    • Ver Perfil
    • El blog de Once
  • Twitter: @don_once
« en: Noviembre 22, 2013, 01:46:12 am »
Hola, sé que en internet se encuentran multitud de ejemplos acerca de
cómo hacer lo que voy a explicar a continuación pero como no es la primer
vez que me lo preguntan, decidí escribir este pequeño tutorial y
explicarlo lo más sencillo que pueda:

¿Qué usaremos?
  • Python 2.7

Problemas con los sockets:

En python es muy fácil escribir aplicaciones cliente/servidor, sólo
tenemos que echar mano de la libreria nativa You are not allowed to view links. Register or Loginde Python.

Pero una vez comenzamos a trabajar con ésta libreria, nos damos cuenta
que se nos presentan un par de problemas o incovenientes que a veces no
hallamos la manera de solucionar, entre ellos se encuentra que el método
del objeto socket sólo nos permite recibir hasta una cantidad
FIJA de bytes.

Sí se envian datos menores o iguales a la cantidad establecida en nuestro
método recv recibiremos el mensaje sin problemas. Pero ¿y si el mensaje
es mayor a la cantidad de bytes establecidos?

La solución:

La solución es relativamente sencilla, pero suele ser un poco confusa así
que intentaré explicarlo de la forma más sencilla.

Programaremos un protocolo para nuestro cliente servidor.

Muy bonito todo, pero, ¿Qué es un protocolo?

Definamos protocolo como un simple conjunto de reglas que usan dos máquinas
para comunicarse. Por ejemplo: si dos personas (un bartener y un cliente)
hablan idiomas distintos (inglés y español) jamás se entenderán y el cliente
jamás obtendra su cerveza; pero si hablan el mismo idioma (inglés-inglés o español-español)
se entenderán y el cliente tendrá su cerveza y el bartender su dinero.

En este ejemplo, el idioma -ya sea español o inglés- es el protocolo que
las dos máquinas (el cliente y el bartender) usan para comunicarse, pero tienen
que usar el mismo protocolo -hablar el mismo idioma-.

Sí hasta ahora has entendido, nuestro siguiente paso será diseñar nuestro
protocolo

Ahora sí, manos a la obra:

Antes definamos el trabajo de cada aplicación:

Cliente: Se encargará de enviar el archivo
Servidor: Se encargará de recibir y guardar el archivo en el disco duro

Teniendo en cuenta esto, ya nos damos una idea de lo que queremos hacer:
el cliente enviará la longitud (cantidad de bytes) del archivo que quiere enviar, el servidor
recibe la longitud y se prepara para recibir el archivo; avisa al cliente
que está listo para recibir el archvio. El cliente envia el archivo.

You are not allowed to view links. Register or Login

En la imagen de arriba (disculpen el paint :P), trato de explicar un poco mejor
cómo funcionará nuestro protocolo.

Las líneas rojas representan los datos que son enviados por el cliente hacía el servidor
Las líneas amarillas representan los datos que son enviados por el servidor hacía el cliente
Los bloques negros -los que parecen una T- significan que los datos que son recibidos
deben ser verificados para continuar.

Básicamente quedaría así:

Cliente: Enviar longitud archivo.
Servidor: Comprobar la longitud (debe ser un número).
Servidor: En caso que la longitud sea correcta, avisar al cliente para que envie al archivo.

Cliente: Comprobar que el servidor está listo.
Cliente: Enviar archivo al servidor.

Código del cliente:

Código: Python
  1. # -*- coding: utf-8 -*-
  2.  
  3. # Envio de archivos: cliente
  4. # 11Sep
  5.  
  6. import socket
  7.  
  8. # Creamos una lista con la dirección de
  9. # la máquina y el puerto donde
  10. # estara a la escucha
  11. CONEXION = (socket.gethostname(), 9001)
  12. ARCHIVO = "a.pdf"
  13.  
  14.  
  15. # Instanciamos el socket y nos
  16. # conectamos
  17. cliente = socket.socket()
  18. cliente.connect(CONEXION)
  19.  
  20. # Abrimos el archivo en modo lectura binaria
  21. # y leemos su contenido
  22. with open(ARCHIVO, "rb") as archivo:
  23.     buffer = archivo.read()
  24.  
  25. while True:
  26.     # Enviamos al servidor la cantidad de bytes
  27.     # del archivo que queremos enviar
  28.     print "Enviando buffer"
  29.     cliente.send(str(len(buffer)))
  30.    
  31.     # Esperamos la respuesta del servidor
  32.     recibido = cliente.recv(10)
  33.     if recibido == "OK":
  34.         # En el caso que la respuesta sea la correcta
  35.         # enviamos el archivo byte por byte
  36.         # y salimos del while
  37.         for byte in buffer:
  38.             cliente.send(byte)
  39.         break

Código del servidor:

Código: Python
  1. # -*- coding: utf-8 -*-
  2.  
  3. # Envio archivos: servidor
  4. # 11Sep
  5.  
  6. import socket
  7.  
  8. # Creamos una lista con los datos del la conexión
  9. CONEXION = (socket.gethostname(), 9001)
  10.  
  11. servidor = socket.socket()
  12.  
  13. # Ponemos el servidor a la escucha
  14. servidor.bind(CONEXION)
  15. servidor.listen(5)
  16. print "Escuchando {0} en {1}".format(*CONEXION)
  17. # Aceptamos conexiones
  18. sck, addr = servidor.accept()
  19. print "Conectado a: {0}:{1}".format(*addr)
  20. while True:
  21.     # Recibimos la longitud que envia el cliente
  22.     recibido = sck.recv(1024).strip()
  23.     if recibido:
  24.         print "Recibido:", recibido
  25.     # Verificamos que lo que recibimos sea un número
  26.     # en caso que así sea, enviamos el mensaje "OK"
  27.     # al cliente indicandole que estamos listos
  28.     # para recibir el archivo
  29.     if recibido.isdigit():
  30.         sck.send("OK")
  31.        
  32.         # Inicializamos el contador que
  33.         # guardara la cantidad de bytes recibidos
  34.         buffer = 0
  35.         # Abrimos el archivo en modo escritura binaria
  36.         with open("archivo", "wb") as archivo:
  37.             # Nos preparamos para recibir el archivo
  38.             # con la longitud específica
  39.             while (buffer <= int(recibido)):
  40.                 data = sck.recv(1)
  41.                 if not len(data):
  42.                     # Si no recibimos datos
  43.                     # salimos del bucle
  44.                     break
  45.                 # Escribimos cada byte en el archivo
  46.                 # y aumentamos en uno el buffer
  47.                 archivo.write(data)
  48.                 buffer += 1
  49.            
  50.             if buffer == int(recibido):
  51.                 print "Archivo descargado con éxito"
  52.             else:
  53.                 print "Ocurrió un error/Archivo incompleto"
  54.         break

Como pueden ver, el código no es nada del otro mundo. Eso sí,
nuestro protocolo tiene un par de fallos potenciales que queda en sus
manos encontrar y solucionar.

Saludos!
11Sep.






You are not allowed to view links. Register or Login

Conectado ANTRAX

  • *
  • Administrator
  • Mensajes: 5267
  • Actividad:
    48.33%
  • Reputación 26
  • ANTRAX
    • Ver Perfil
    • Underc0de
    • Email
  • Skype: underc0de.org
  • Twitter: @Underc0de
« Respuesta #1 en: Noviembre 22, 2013, 07:54:33 am »
Que excelente aporte 11sep!
Muchisimas gracias bro!

Saludos!


Desconectado Once

  • *
  • Underc0der
  • Mensajes: 383
  • Actividad:
    0%
  • Reputación 0
    • Ver Perfil
    • El blog de Once
  • Twitter: @don_once
« Respuesta #2 en: Noviembre 22, 2013, 08:59:08 pm »
Gracias bro, si tengo tiempo haré un par más para resolver esas dudas tan repetitivas que me hacen por privado.

Saludos!






You are not allowed to view links. Register or Login

Desconectado rezyckller

  • *
  • Underc0der
  • Mensajes: 41
  • Actividad:
    0%
  • Reputación 0
  • Lo unico seguro es que es inseguro.
    • Ver Perfil
    • Invisible Research
    • Email
« Respuesta #3 en: Noviembre 23, 2013, 04:15:22 am »
Muy bueno el aporte 11sep!
 Ya se me ocurrieron algunas formas de aplicarlo.  :D

Saludos!


Desconectado alexander1712

  • *
  • Underc0der
  • Mensajes: 851
  • Actividad:
    0%
  • Reputación -2
    • Ver Perfil
    • El blog del programador
    • Email
« Respuesta #4 en: Noviembre 23, 2013, 10:11:41 am »
muy bueno 11

un saludo!

 

¿Te gustó el post? COMPARTILO!



Tutorial Django by cybernatural

Iniciado por Flemon

Respuestas: 5
Vistas: 2228
Último mensaje Febrero 14, 2013, 11:07:03 am
por Snifer
Tutorial de Python 3

Iniciado por Expermicid

Respuestas: 2
Vistas: 1471
Último mensaje Mayo 04, 2013, 04:54:25 am
por TeNeX
[Codigo + Introduccion] Manejo de archivos csv en python

Iniciado por blozzter

Respuestas: 2
Vistas: 6483
Último mensaje Abril 01, 2012, 05:43:38 pm
por pab mac
[Python] Descargar Archivos - by NiKo

Iniciado por ProcessKill

Respuestas: 3
Vistas: 3264
Último mensaje Noviembre 03, 2012, 11:50:45 am
por BigBear
Moviendonos entre archivos con python

Iniciado por Once

Respuestas: 6
Vistas: 3387
Último mensaje Enero 23, 2015, 12:30:11 am
por Azav