comment
IRC Chat
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

  • 10 Respuestas
  • 7445 Vistas

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

Desconectado Once

  • *
  • Underc0der
  • Mensajes: 391
  • 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 No tienes permisos para ver links. Registrate o Entra con tu cuentade 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.

No tienes permisos para ver links. Registrate o Entra con tu cuenta

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.






No tienes permisos para ver links. Registrate o Entra con tu cuenta

Conectado ANTRAX

  • *
  • Administrator
  • Mensajes: 5401
  • Actividad:
    38.33%
  • Reputación 31
  • 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: 391
  • 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!






No tienes permisos para ver links. Registrate o Entra con tu cuenta

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: 850
  • 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!

Desconectado jcamiloce10

  • *
  • Underc0der
  • Mensajes: 3
  • Actividad:
    0%
  • Reputación 0
    • Ver Perfil
    • Email
« Respuesta #5 en: Julio 22, 2018, 06:20:52 pm »
Hola disculapame estoy itentando enviar esto datos = [1,2,3,4....8000] solo es una prueba pues nesesito hacer lo mismo con unos datos que vienen de un sensor, mas o menos 8mil datos por segundo, mi preugunta es, como lo hago puesto que cuando intento enviar la prueba que mostre anteriormente, me sale el siguiente error "sendall() argument 1 must be string or buffer, not list", y la verdad no se que hacer, espero puedas ayudarme

Desconectado Once

  • *
  • Underc0der
  • Mensajes: 391
  • Actividad:
    0%
  • Reputación 0
    • Ver Perfil
    • El blog de Once
  • Twitter: @don_once
« Respuesta #6 en: Julio 22, 2018, 10:52:36 pm »
Hola jcamiloce10, mira que el mismo error te lo está diciendo, no puedes enviar una lista, puedes enviar un string, lo que implica que para enviar la lista debes hacerlo elemento por elemento.

Ahora, mencionas un sensor, explícame mejor que es lo que estás intentando hacer (o crea un post nuevo) así te puedo ayudar mejor, puesto que si vas a usar un sensor, lo que vas a necesitar es, probablemente, usar el protocolo serial. Así que, por favor, danos más información.

Saludos.






No tienes permisos para ver links. Registrate o Entra con tu cuenta

Desconectado jcamiloce10

  • *
  • Underc0der
  • Mensajes: 3
  • Actividad:
    0%
  • Reputación 0
    • Ver Perfil
    • Email
« Respuesta #7 en: Julio 22, 2018, 11:28:32 pm »
Hola Once, bueno la explicación es la siguiente. Estoy realizando un trabajo con el sensor ADS1298 para electrocardiografia, este sensor lo tengo conectado a una raspberry pi zero w, por medio de protocolo SPI (es el único protocolo que admite el sensor). El sensor ya me entrega convertidos a digital los datos en tramas de aproximadamente 216 bits cada una, es decir me da una "lista" de 27 bytes o 27 posiciones. Mi objetivo es enviar vía WIFI esos datos, es decir 8mil tramas cada segundo, que me entrega el sensor desde la raspberry pi zero w hacia un computador que funja como servidor o receptor, para que este los almacene y los procese de manera rápida y adecuada. Para eso he buscado varios protocolos de transmisión inalámbrica como el ssh (protocolo que es muy pesado por su necesidad de cifrar cada dato enviado a 128 bits), el protocolo MQTT, pero no he encontrado mucha información ni como programarlo en python, y luego están los sockets, que pienso puede ser una buena opcion para mi problema, esa es a grandes rasgos la explicación, espero no haberme extendido mucho, espero que puedas ayudarme, si tienes una sugerencia por esta temática, o conoces un protocolo de comunicación wifi que me permita hacerlo te lo agradecería, y por cierto muchas gracias por tu atención!

Desconectado Once

  • *
  • Underc0der
  • Mensajes: 391
  • Actividad:
    0%
  • Reputación 0
    • Ver Perfil
    • El blog de Once
  • Twitter: @don_once
« Respuesta #8 en: Julio 24, 2018, 01:07:27 pm »
En ese caso, como te ddije al principio, lo mejor es que envies los datos de la lista uno por uno, puesto que no puedes enviar la lista como tal, otra opción seria que serialices la lista antes de enviarla, así seria como si enviaras un archivo de texto, y luego, cuando la recibes, deserializas. Para serializar simplemente usas el módulo No tienes permisos para ver links. Registrate o Entra con tu cuenta

Saludos!






No tienes permisos para ver links. Registrate o Entra con tu cuenta

Desconectado jcamiloce10

  • *
  • Underc0der
  • Mensajes: 3
  • Actividad:
    0%
  • Reputación 0
    • Ver Perfil
    • Email
« Respuesta #9 en: Julio 26, 2018, 09:53:08 pm »
Once, te agradezco tu ayuda!, funciono perfectamente la serializacion, en serio haz sido de mucha ayuda!

Desconectado Once

  • *
  • Underc0der
  • Mensajes: 391
  • Actividad:
    0%
  • Reputación 0
    • Ver Perfil
    • El blog de Once
  • Twitter: @don_once
« Respuesta #10 en: Julio 27, 2018, 07:53:10 pm »
Un placer poderte ayudar, cualquier otra duda que tengas, no dudes en preguntar.

Saludos!






No tienes permisos para ver links. Registrate o Entra con tu cuenta

 

¿Te gustó el post? COMPARTILO!



Tutorial Django by cybernatural

Iniciado por Flemon

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

Iniciado por Expermicid

Respuestas: 2
Vistas: 1636
Ú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: 7660
Último mensaje Abril 01, 2012, 05:43:38 pm
por pab mac
[Python] Descargar Archivos - by NiKo

Iniciado por ProcessKill

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

Iniciado por Once

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