Y que es lo grandioso de los sockets??
Para todos aquellos que estan comenzando a desesperarse porque no hemos hecho aplicaciones utiles, pues ahora
vamos a realizar un tipo de chat, no es muy estetico, pero es un comienzo.
# servchat.py
# Creamos un servidor de chat.
# Juan Francisco Benavides Nanni - Dracko - 17/02/2006
import socket
import select
def accept_new_connection():
try:
global server
global desc
newsock, (remhost, remport) = server.accept()
server.settimeout(.1)
print "Se ha conectado %s:%s" % (str(remhost), str(remport))
desc.append(newsock)
except:
pass
def broadcast(msg, sock):
global desc
global server
host, port = sock.getpeername()
msg = "[%s:%s]: %s" % (str(host), str(port), str(msg))
for destsock in desc:
if destsock != sock and destsock != server:
destsock.send(msg)
def get_msg(sock):
try:
msg = sock.recv(1024)
sock.settimeout(.1)
return msg
except:
global desc
host, port = sock.getpeername()
print "[%s:%s] ha salido." % (str(host), str(port))
desc.remove(sock)
return None
global server
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("", 8000))
server.listen(5)
global desc
desc = [server]
while 1:
accept_new_connection()
(sread, swrite, sexc) = select.select(desc, [], [])
for sock in sread:
if sock != server:
flag = get_msg(sock)
if flag:
broadcast(flag, sock)
Bajar codigo.
Pues a mi parecer esto se puso interesante, como se acaban de dar cuenta hemos dado un gran paso, de unos simples Scripts
que solo aceptaban conexiones y mandaban un mensaje, dimos un giro al realizar una aplicacion que maneje "usuarios" y los
comunique, la verdad es que esa no es la unica manera de hacer un servidor de chat, bueno la base de uno, hay infinidad
de maneras, talvez esta incluso sea una pesima manera de realizarlo, pero funciona para nuestros propositos de este tutorial.
Muy bien, a la explicación:
# servchat.py
# Creamos un servidor de chat.
# Juan Francisco Benavides Nanni - Dracko - 17/02/2006
import socket
import select
Lo unico diferente aqui es que ahora incluimos el modulo de select, no se preocupen, será explicado en su debido
momento.
global server
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("", 8000))
server.listen(5)
global desc
desc = [server]
while 1:
accept_new_connection()
(sread, swrite, sexc) = select.select(desc, [], [])
for sock in sread:
if sock != server:
flag = get_msg(sock)
if flag:
broadcast(flag, sock)
Despues pasamos a las funciones, primero hay que entender lo que se espera realizar, muy bien, estamos creando variables
globales (
global), para que estas puedan ser modificadas en las funciones, despues creamos el
servidor, asignandole una direccion y un puerto, despues hacemos el ciclo infinito el cual ya fue explicado, y ya adentro
de ese ciclo aceptamos nuevas conexiones (
accept_new_connection()), ahora sigue lo del select,
como pueden ver le estamos mandando una lista donde se encuentran los sockets que se estan usando (incluyendo el server)
lo unico que nos importa es saber cuando un socket se intenta comunicar con el servidor, es por eso que los otros dos
parametros los dejamos vacios (select.select(desc,
[],
[])), el
select nos devolvera los que se intentan comunicar, despues verificamos cada elemento que nos fue regresado (excluyendo
al server (
if sock != server:)) para saber que es lo que intenta hacer, despues recivimos el
mensaje de cada socket que se comunicó (
get_msg()) y lo mandamos a todos
(
broadcast()), dentro de la función de
get_msg() también
verifica que siga conectado ese cliente.
def accept_new_connection():
try:
global server
global desc
newsock, (remhost, remport) = server.accept()
server.settimeout(.1)
print "Se ha conectado %s:%s" % (str(remhost), str(remport))
desc.append(newsock)
except:
pass
Lo que esta haciendo esta función es utilizar las variables globales, para poderlas modificar, entonces lo que intenta
es recivir una nueva conexion, pero solo lo hace por un periodo corto de tiempo (server.settimeout(.1)), si ese tiempo se acaba
se pasa a la esepción la cual no hace nada, pero si en ese tiempo llega una nueva conexion entonces la acepta y
guarda el nuevo socket en la lista (desc.append(newsock)).
def get_msg(sock):
try:
msg = sock.recv(1024)
sock.settimeout(.1)
return msg
except:
global desc
host, port = sock.getpeername()
print "[%s:%s] ha salido." % (str(host), str(port))
desc.remove(sock)
return None
En esta función intentamos recivir un mensaje (msg = sock.recv(1024)) del socket que pasamos como parametro, pero una véz más
le dejamos un tiempo limite, si ese tiempo es excedido significa que el cliente se ha desconectado y lo quitamos de la
lista, y devolvemos None, para que no entre a la condicional que tenemos en el programa principal.
Pero si nos manda un mensaje lo regresamos para que entre a la codicional en el programa principal, y ahi sera llamada
la siguiente función:
def broadcast(msg, sock):
global desc
global server
host, port = sock.getpeername()
msg = "[%s:%s]: %s" % (str(host), str(port), str(msg))
for destsock in desc:
if destsock != sock and destsock != server:
destsock.send(msg)
lo que realiza esta función es utilizar las variables globales para asi mandar un "broadcast", el mensaje que
recive como parametro es lo que mandara a todos.
Se verá algo como esto: