La comunicación entre distintas entidades en una red se basa en Python en el clásico concepto de sockets. Los sockets son un concepto abstracto con el que se designa al punto final de una conexión.
Los programas utilizan sockets para comunicarse con otros programas, que pueden estar situados en computadoras distintas.
Un socket queda definido por la dirección IP de la máquina, el puerto en el que escucha, y el protocolo que utiliza.
Los tipos y funciones necesarios para trabajar con sockets se encuentran en Python en el módulo socket
, como no podría ser de otra forma.
Los sockets se clasifican en sockets de flujo (socket.SOCK_STREAM
) o sockets de datagramas (socket.SOCK_DGRAM
) dependiendo de si el servicio utiliza TCP, que es orientado a conexión y fiable, o UDP, respectivamente. En esta lección sólo cubriremos los sockets de flujo, que cubren un 90% de las necesidades comunes.
Los sockets también se pueden clasificar según la familia. Tenemos sockets UNIX (socket.AF_UNIX
) que se crearon antes de la concepción de las redes y se basan en ficheros, sockets socket.AF_INET
que son los que nos interesan, sockets socket.AF_INET6
para IPv6, etc.
Para crear un socket se utiliza el constructor socket.socket()
que puede tomar como parámetros opcionales la familia, el tipo y el protocolo. Por defecto se utiliza la familia AF_INET y el tipo SOCK_STREAM.
Veremos durante el resto de la lección cómo crear un par de programas cliente y servidor a modo de ejemplo.
Lo primero que tenemos que hacer es crear un objeto socket para el servidor
socket_s = socket.socket()
Tenemos ahora que indicar en qué puerto se va a mantener a la escucha nuestro servidor utilizando el método bind
. Para sockets IP, como es nuestro caso, el argumento de bind
es una tupla que contiene el host y el puerto. El host se puede dejar vacío, indicando al método que puede utilizar cualquier nombre que esté disponible.
socket_s.bind(("localhost", 9999))
Por último utilizamos listen
para hacer que el socket acepte conexiones y accept
para comenzar a escuchar. listen
requiere de un parámetro que indica el número de conexiones máximas que queremos aceptar; evidentemente, este valor debe ser al menos 1.
accept
se mantiene a la espera de conexiones entrantes, bloqueando la ejecución hasta que llega un mensaje.
Cuando llega un mensaje, accept
desbloquea la ejecución, devolviendo un objeto socket
que representa la conexión del cliente y una tupla que contiene el host y puerto de dicha conexión.
socket_s.listen(10) socket_c, (host_c, puerto_c) = socket_s.accept()
Una vez que tenemos este objeto socket podemos comunicarnos con el cliente a través suyo, mediante los métodos recv
y send
(o recvfrom
y sendfrom
en UDP) que permiten recibir o enviar mensajes respectivamente. El método send
toma como parámetros los datos a enviar, mientras que el método recv
toma como parámetro el número máximo de bytes a aceptar.
recibido = socket_c.recv(1024) print "Recibido: ", recibido socket_c.send(recibido)
Una vez que hemos terminado de trabajar con el socket, lo cerramos con el método close
.
Crear un cliente es aún más sencillo. Solo tenemos que crear el objeto socket
, utilizar el método connect
para conectarnos al servidor y utilizar los métodos send
y recv
que vimos anteriormente. El argumento de connect
es una tupla con host y puerto, exactamente igual que bind.
socket_c = socket.socket() socket_c.connect(("localhost", 9999)) socket_c.send("hola")
Veamos por último un ejemplo completo. En este ejemplo el cliente manda al servidor cualquier mensaje que escriba el usuario y el servidor no hace más que repetir el mensaje recibido. La ejecución termina cuando el usuario escribe «quit».
Este sería el código del script servidor:
import socket s = socket.socket() s.bind(("localhost", 9999)) s.listen(1) sc, addr = s.accept() while True: recibido = sc.recv(1024) if recibido == "quit": break print "Recibido:", recibido sc.send(recibido) print "adios" sc.close() s.close()
Y a continuación tenemos el del script cliente:
import socket s = socket.socket() s.connect(("localhost", 9999)) while True: mensaje = raw_input("> ") s.send(mensaje) if mensaje == "quit": break print "adios" s.close()
Hola, que plugin utilizas para mostrar el código de esa forma? Gracias.
Excelente la iniciativa de enseñar python.
Saludos.
Es dp.SyntaxHighlighter, un engine basado en JavaScript.
Lo que aprende uno en tu blog. Gracias por los posts sobre python.
Muy bueno, muchas gracias. Si pudieras hacer un post uniendo sockets y threads te lo agradeceria mucho.
Gracias sigue asi =)
Pues primero voy a hablar un poco de urllib y urllib2 y lo siguiente seguramente sean threads.
Pingback: Servidor y Cliente TCP en Python
Gracias ;). Es genial!
Buenisimo el tutorial, espero que se amplie 🙂
Pingback: .:: Blog Satélite Guayana ::. » Taller en python…
Muy buena copia del libro «Python para todos». Al menos podías haber puesto la fuente.
Perdona Zootropo. Ni caso, no me fijé en los post anteriores. Un millón de disculpas.
Tranquilo, no pasa nada 🙂
La verdad es que debería enlazar mi libro desde cada una de las entradas en las que se basa para evitar estas confusiones y propiciar que la gente lo encontrara más fácilmente vía Google. Quizás lo haga cuando tenga un rato.
Lo que no entiendo es la linea 14 del servidor, ya que sc es el socket que recive datos no entiendo porque ha de enviar datos 🙂
Todo esta info está extraída textualmente del manual que está dando vueltas en la web Python_para_todos.pdf. Pueden buscarlo está muy completo. ESTUVISTE MAL EN NO PONER LA FUENTE !!!
Un manual del cuál yo soy el autor, amigo mío: Python para todos.
Y esta y las demás entradas que puedes encontrar en el blog con la etiqueta python son los textos en los que se basa.
Agradezco el que intentaras defender mis derechos, no obstante 😉
jajajajja… como anecdota me ha hecho reirrr!!! jejej…
gracias por el aporte!!!
Muy buen material! Gracias
Me podras dar una mano? necesito que el script escuche en todos los puertos (o varios) y me muestre paquetes. Gracias!
Hola.. Gracias.. Me por el ejemplo.. muy detallado..!
oye deberias pasarte a foros portal hacker con tus conocimientos
Es posible mediante sockets comunicar peticiones a servidores PHP hasta un proceso en python?
no se puede prrooo
Creo que hay un error, en cierto momento pones «o recvfrom y sendfrom en UDP» pero creo que «sendfrom» no existe en realidad se trata de «sendto» (no estoy seguro porque soy principiante en Python).
Muy bueno el post, me sirvió un montón y ya estoy bajando el pdf 🙂
hola Zootropo,
tengo intencion de hacer una palicacion con PYMT. la idea es hacer una especie de messenger pero con ventanas multitactiles, la pregunta es como puedo pasar los datos de una imagen o video, que supongo que a la practica es lo mismo, desde un servidor TCP,
gracias de antemano
Hola estoy empezando a estudiar python porque puede ser una herramienta muy util en la carrera que estoy estudiando (Ing en Telecomunicaciones), no entiendo la utilidad de la linea 14 sc.send(recibido) en el codigo del servidor, muchas gracias
necesito hacer eso mismo pero desde maquinas distinas, este codigo funciona muy pero en la misma maquina, cuando lo corro el servidor en una maquina distina al cliente no hace nada, y en el cliente me da connection refused, como puedo lograr esto, gracias de antemano…
Zopotropo, sé que el post es antiguo, pero nadie se ha «quejado» al respecto. Hay una typo en el cuarto bloque de código, en la línea que pone:
> print «Recibido: «, recibio
Cuando en realidad debería poner:
> print «Recibido: «, recibido
El post es genial: simple y fácil. Si simplemente se puediese arreglar este pequeño error de sintaxis ya sería perfecto. Un saludo.
Vaya, muy buen ojo. Ya lo he arreglado.
Muchas gracias 🙂
buenisimo !!! muchas gracias!
Pingback: Sistema Distribuido Cliente/Servidor #Python | @l30bravo
HOLA MEN COMO ESTAS?
estoy programando SOCKETS & TKinteR…
DEBE HACER UN MINI CHAT CON GRAFICOS DE SERVER Y USER..
AL INCIAR EL SERVER ESTA BN.. EL USER AL CONECTAR .. BN…
EL USER ENVIA SALUDO PERO EL SERVER NO DA RESPUESTA
PORQUE UN BOTON LLAMADO ENVIAR O DAR «ENTER» NO CONECTA… cliente , datos_clientes=servidor.accpet()
la funcion del boton
def env:
cliente.send(bytes(t2.get(),’utf-8′))
donde t2 es el cuadro de texto q escribe el server para enviar.. pero el programa da error con cliente ahi despues de DEF ENV: y no envia respuesta al server
si me comunicas te mando los archivos
gracias
Cuando lanzo el programa me lanza el error
File «», line 1, in
File «socket.py», line 2, in
s = socket.socket()
TypeError: ‘module’ object is not callable
Soy bastante nuevo en python y no consigo saber que puede ser. Gracias
Enorme aporte tus posts sobre python, quería preguntar una cosa sobre los sockets, estoy intentando crear un mini programa que capture los paquetes que llegan a un cliente de poker para hacer un mini porgrama de pruebas, ¿esto se haría con los sockets? es decir, averiguar a qué puerto se contecta este cliente para conectar con el servidor y intentar escuchar ese puerto o necesito otra cosa? Muchas gracias
muy bueno
Hola, Muy buen aporte, soy apenas un principiante, estoy tratando de correr el código, pero siempre me sale el winerror 10061 y he hecho de todo. Habilitar los puertos, desactivar el firewall, etc y es imposible para mí, me siento muy frustrado.
Por favor ayúdeme profesor !
Bueno uso PYDEV y lo copie y pegue y edite el error mencionado, y no sale, da fustracion, tan dificil es esto de los zockets, cuando ingreso texto a input, sale infinitamente:
Recibido: b»
Recibido: b»
Recibido: b»
Recibido: b»
………….
………….
haber si alguien me ayuda grcias.
por cierto que IDE usas amigo wn window no sale el programa.
O:
Por lo visto Python es increíblemente fácil a comparación de otros lenguajes, creo comenzaré a estudiar más éste lenguaje.
Pingback: Conexión vía socket con python | Satélite Guayana
Conocen alguna manera para poder llamar un procedimiento al terminar de subir un archivo .csv a un servidor SFTP usando sockets?
yo tengo un problema tengo que crear un servidor web con este codigo
##================ server.py ============================
## autor: Carlos Castillo
## descripción:
## Este codigo crea un servidor Web basico en python.
## Referencias:
## http://docs.python.org/3.2/howto/sockets.html
##=========================================================
#import socket
from socket import *
serverSocket = socket(AF_INET, SOCK_STREAM)
#Prepara un socket del servidor
serverSocket.bind((‘172.201.110.121’, 1769))
listen(1)
#Envia un mensaje debidamente codificado por el socket
def sendThroughSocket(message):
connectionSocket.send(oupud.encode(‘utf8’))
#Recibe un mensaje debidamente codificado por el socket
def receiveThroughSocket():
return connectionSocket.recv(2048).decode(‘utf8’)
while True:
#Establece la conexión
print (‘Ready to serve…’)
connectionSocket, addr = serverSocket.accept()
try
message = connectionSocket.recv(1024)
print message, ‘::’, message.split()[0],’:’, message.split()[1]
filename = message.split()[1]
print filename, ‘||’, filename[1:]
f = open(filename[1:])
outputdata = f.read()
print outputdata
connectionSocket.send(‘\HTTP:172.201.110.121:1769/HelloWorld.html/1.1 200 OK\n\n’)
connectionSocket.send(outputdata)
connectionSocket.colse()
#Envia el contenido del archivo solicitado al cliente
for i in range(0, len(outputdata)):
connectionSocket.send(outputdata.encode(‘utf8’))
connectionSocket.close()
except IOError:
#Envia la respuesta si no encontro el archivo
##llene codigo INICIO
##llene codigo FINAL
except Exception as e:
print(e)
connectionSocket.close()
#Cierra el socket del servidor
##llene codigo INICIO
para presentar una pagina en html que diga hola mundo y no puedo encontrar todo el codigo para que funcione
Muchas gracias por el aporte.
Hola, quisiera saber como puedes usar los sockets para establecer una conexion entre dos ordenadores que no esten en la misma red, por ejemplo el mio y otro que este en Alemania.
Hola, quisiera saber como puedes usar los sockets para establecer una conexion entre dos ordenadores que no esten en la misma red, por ejemplo el mio y otro que este en Alemania.
Este es el correcto, el otro no recibo e-mail.
Si alguien puede ofrecerme ayuda más compleja que me pida mi e-mail y yo se lo doi.
Alguien me podría decir como hacer de este script (el del ejemplo expuesto) funcional bajo plataforma Windows? Es necesario utilizar otras funciones de la librería «socket»? o es que definitivamente solo se puede bajo linux.
Hola, fijate que no me compila la parte del cliente
en python y donde me aparece el error es el metodo de connect
basura ql copyright