La computación concurrente es la capacidad de simultanear en la ejecución de múltiples tareas interactivas. Un proceso es un programa en ejecución, que es gestionado por el Sistema Operativo y compite por los recursos del procesador. Los procesos tienen estado y memoria en ejecución reservada. El mecanismo por el cual un proceso crea otro proceso se denomina bifurcación (fork). Cuando un proceso se bifurca, se crea una copia exacta del proceso en ejecución, independiente del resto y no comparte el espacio de memoria con el proceso que los ha creado ni con otros procesos.
Un hilo, en sistemas operativos, es una característica que permite a una aplicación realizar varias tareas a la vez (concurrentemente). Los distintos hilos de ejecución comparten una serie de recursos tales como el espacio de memoria, o los archivos abiertos. Esta técnica permite simplificar el diseño de una aplicación que debe llevar a cabo distintas funciones simultáneamente. Un hilo es un tarea que se ejecuta en paralelo con otra tarea.
La comunicación entre el cliente y el servidor se hace posible gracias a estructuras abstractas denominadas sockets, mediante las cuales los programas pueden intercambiar flujo de datos e información. Este concepto está asociado al concepto de puerto.
Un puerto es una forma genérica de denominar a una interfaz a través de la cual los diferentes tipos de datos se pueden enviar y recibir. En el protocolo TCP/IP, son de tipo lógico, por ejemplo, los puertos que permiten la transmisión de datos entre diferentes computadores.
Existen dos tipos de sockets, orientados a conexión y no orientados a conexión. La diferencia fundamental es que en los sockets orientados a conexión (TCP) el protocolo garantiza que los datos serán entregados en su destino sin errores y en el mismo orden en que se transmitieron, mientras que en los sockets no orientados a conexión (o UDP) no se garantiza que el mensaje llegue a su destino. Parece claro que si el programa envía un mensaje y no hay nadie escuchando, ese mensaje se pierde. De todas formas, aunque haya alguien escuchando, el protocolo tampoco garantiza que el mensaje llegue. Lo único que garantiza es, que si llega, llega sin errores.
En una comunicación con sockets multihilo, como es el caso de la implementación que nos ocupa, cada conexión es gestionada por un proceso o hilo de ejecución independiente. Así, con cada cliente que conecte con el servidor, se expande un nuevo hilo del lado del servidor, que gestionará las peticiones del cliente asociado a él. Servidores concurrentes pueden ser multiproceso o multihilo. Estos son utilizados para servicios largos con mucha sincronización Cliente-Servidor.
A continuación dejo el código de ambas implementaciones, primero en C++ y después en Python.
Comandos
- ADD usuario:Introduce un usuario en el chat.
- LIST: Obtiene la lista de clientes conectados.
- END: Desconecta y sale de la sesión.
- TEXT: Envía un mensaje a todos los usuarios conectados.
- TEXT TO usuario: Envía un mensaje privado a un usuario.
En C++
Servidor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
| #include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#define SERVER_PORT 6543
#define SERVER_ADDRESS "127.0.0.1"
#define MAXLINE 512
#define MAXCLIENTS 10
int buscarCliente(char*);
void subCadena(char*, char*, int, int);
struct vector
{
int socket;
char usuario[MAXLINE-4];
int sign_in;
};
struct vector vectorClientes[MAXCLIENTS];
int clientes = 0;
int main(int argc, char *argv[])
{
void* gestionaCliente(void* p);
int socketfd, new_sd;
socklen_t client_len;
struct sockaddr_in server_addr, client_addr;
int i, status, id;
pthread_t hilos[MAXCLIENTS];
for(i=0;i<MAXCLIENTS;i++)
strcpy(vectorClientes[i].usuario, " ");
// Open TCP internet STREAM socket
if ((socketfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
perror("server: Can't open stream socket");
// Bind local address to allow the client to connect
bzero((char *) &server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(SERVER_PORT);
if (bind
(socketfd, (struct sockaddr *) &server_addr,
sizeof(server_addr)) < 0)
perror("server: can't bind local address");
listen(socketfd, 5);
for (;;) {
client_len = sizeof(client_addr);
if((new_sd = accept(socketfd, (struct sockaddr *) &client_addr, &client_len)) < 0) {
printf("Error aceptando peticiones\n");
exit(0);
}
else {
id = clientes;
vectorClientes[id].socket = new_sd;
vectorClientes[id].sign_in = 0;
fflush(stdout);
clientes++;
if ( (status = pthread_create(&hilos[id],NULL,gestionaCliente,(void *)&id)) )
{
printf("Error al crear el hilo\n");
exit(0);
}
}
}
close(socketfd); // Close original socket
return 0;
}
void subCadena(char *subCad, char *cad, int inicio, int cuantos)
{
int i,j=0;
for(i=inicio;i<inicio+cuantos && cad[i]!='\0';i++)
{
subCad[j]=cad[i];
j++;
}
subCad[j]='\0';
}
int buscarCliente(char* usuario)
{
int i;
for(i=0;i<clientes;i++)
{
if(strcmp(vectorClientes[i].usuario,usuario ) == 0 && vectorClientes[i].sign_in == 1)
return vectorClientes[i].socket;
}
return -1;
}
void* gestionaCliente(void* p)
{
int *ide, id;
ide = (int* ) p;
id = *ide;
char buffer[MAXLINE], nombre[MAXLINE-4], temp[MAXLINE-8];
int i, longitud, destino;
while(1)
{
recv(vectorClientes[id].socket,buffer,MAXLINE,0);
printf("\nid%d\n", id);
if(strstr(buffer, "ADD") && vectorClientes[id].sign_in == 0) {
longitud = strlen(buffer);
//Le quitamos el ADD
subCadena(nombre, buffer, 4, longitud-4);
strcpy(vectorClientes[id].usuario, nombre);
//Se informa a todos menos a él mismo y al que se haya ido
strcpy(buffer, "El usuario ");
strcat(buffer, nombre);
strcat(buffer, " ha entrado en el chat.");
for(i = 0; i < clientes; i++)
if (i != id && vectorClientes[i].sign_in == 1)
send(vectorClientes[i].socket,buffer,MAXLINE,0);
vectorClientes[id].sign_in = 1;
}
if(strstr(buffer, "LIST") && vectorClientes[id].sign_in == 1) {
//Se envia al cliente todos los usuarios menos los que hayan abandonado la sesión
for(i = 0; i < clientes; i++){
if(vectorClientes[i].sign_in == 1)
send(vectorClientes[id].socket, vectorClientes[i].usuario, MAXLINE, 0);
}
}
if(strstr(buffer, "END") && vectorClientes[id].sign_in == 1) {
//Se informa a todos menos a él mismo y al que se haya ido
strcpy(buffer, "El usuario ");
strcat(buffer, vectorClientes[id].usuario);
strcat(buffer, " ha abandonado en el chat.");
bzero(vectorClientes[id].usuario, MAXLINE);
for(i = 0; i < clientes; i++)
if (i != id && vectorClientes[i].sign_in == 1)
send(vectorClientes[i].socket,buffer,MAXLINE,0);
vectorClientes[id].sign_in = 0;
}
if(strstr(buffer, "TEXT") && !strstr(buffer, "TEXT TO") && vectorClientes[id].sign_in == 1) {
longitud = strlen(buffer);
subCadena(temp, buffer, 5, longitud-5);
//Se envía a todos menos a él mismo y al que se haya ido
bzero(buffer, MAXLINE);
strcat(buffer, vectorClientes[id].usuario);
strcat(buffer, " dice: ");
strcat(buffer, temp);
for(i = 0; i < clientes; i++)
if (i != id && vectorClientes[i].sign_in == 1)
send(vectorClientes[i].socket,buffer,MAXLINE,0);
}
if(strstr(buffer, "TEXT TO") && vectorClientes[id].sign_in == 1) {
//Le quitamos el TEXT TO
subCadena(nombre, buffer, 8, MAXLINE-8);
//Nos quedamos sólo con el nombre, quitando desde el primer espacio en blanco hasta el final
strtok(nombre," ");
//Se obtiene el socket destino
destino = buscarCliente(nombre);
longitud=strlen(nombre);
strcpy(nombre, vectorClientes[id].usuario);
strcat(nombre, " dice: ");
//Recortamos el TEXT TO, el nombre, y los dos espacios hasta el mensaje(se suma solo uno (un espacio)
//porque empieza a recorrer longitud(instruccion)+longitud(nombre) desde la pos. 0 de la cadena.
subCadena(temp, buffer, 8+longitud+1, MAXLINE-(8+longitud+1));
strcat(nombre, temp);
if(destino != -1)
send(destino, nombre, MAXLINE, 0);
}
fflush(stdout);
}
close(vectorClientes[id].socket);
} |
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#define SERVER_PORT 6543
#define SERVER_ADDRESS "127.0.0.1"
#define MAXLINE 512
#define MAXCLIENTS 10
int buscarCliente(char*);
void subCadena(char*, char*, int, int);
struct vector
{
int socket;
char usuario[MAXLINE-4];
int sign_in;
};
struct vector vectorClientes[MAXCLIENTS];
int clientes = 0;
int main(int argc, char *argv[])
{
void* gestionaCliente(void* p);
int socketfd, new_sd;
socklen_t client_len;
struct sockaddr_in server_addr, client_addr;
int i, status, id;
pthread_t hilos[MAXCLIENTS];
for(i=0;i<MAXCLIENTS;i++)
strcpy(vectorClientes[i].usuario, " ");
// Open TCP internet STREAM socket
if ((socketfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
perror("server: Can't open stream socket");
// Bind local address to allow the client to connect
bzero((char *) &server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(SERVER_PORT);
if (bind
(socketfd, (struct sockaddr *) &server_addr,
sizeof(server_addr)) < 0)
perror("server: can't bind local address");
listen(socketfd, 5);
for (;;) {
client_len = sizeof(client_addr);
if((new_sd = accept(socketfd, (struct sockaddr *) &client_addr, &client_len)) < 0) {
printf("Error aceptando peticiones\n");
exit(0);
}
else {
id = clientes;
vectorClientes[id].socket = new_sd;
vectorClientes[id].sign_in = 0;
fflush(stdout);
clientes++;
if ( (status = pthread_create(&hilos[id],NULL,gestionaCliente,(void *)&id)) )
{
printf("Error al crear el hilo\n");
exit(0);
}
}
}
close(socketfd); // Close original socket
return 0;
}
void subCadena(char *subCad, char *cad, int inicio, int cuantos)
{
int i,j=0;
for(i=inicio;i<inicio+cuantos && cad[i]!='\0';i++)
{
subCad[j]=cad[i];
j++;
}
subCad[j]='\0';
}
int buscarCliente(char* usuario)
{
int i;
for(i=0;i<clientes;i++)
{
if(strcmp(vectorClientes[i].usuario,usuario ) == 0 && vectorClientes[i].sign_in == 1)
return vectorClientes[i].socket;
}
return -1;
}
void* gestionaCliente(void* p)
{
int *ide, id;
ide = (int* ) p;
id = *ide;
char buffer[MAXLINE], nombre[MAXLINE-4], temp[MAXLINE-8];
int i, longitud, destino;
while(1)
{
recv(vectorClientes[id].socket,buffer,MAXLINE,0);
printf("\nid%d\n", id);
if(strstr(buffer, "ADD") && vectorClientes[id].sign_in == 0) {
longitud = strlen(buffer);
//Le quitamos el ADD
subCadena(nombre, buffer, 4, longitud-4);
strcpy(vectorClientes[id].usuario, nombre);
//Se informa a todos menos a él mismo y al que se haya ido
strcpy(buffer, "El usuario ");
strcat(buffer, nombre);
strcat(buffer, " ha entrado en el chat.");
for(i = 0; i < clientes; i++)
if (i != id && vectorClientes[i].sign_in == 1)
send(vectorClientes[i].socket,buffer,MAXLINE,0);
vectorClientes[id].sign_in = 1;
}
if(strstr(buffer, "LIST") && vectorClientes[id].sign_in == 1) {
//Se envia al cliente todos los usuarios menos los que hayan abandonado la sesión
for(i = 0; i < clientes; i++){
if(vectorClientes[i].sign_in == 1)
send(vectorClientes[id].socket, vectorClientes[i].usuario, MAXLINE, 0);
}
}
if(strstr(buffer, "END") && vectorClientes[id].sign_in == 1) {
//Se informa a todos menos a él mismo y al que se haya ido
strcpy(buffer, "El usuario ");
strcat(buffer, vectorClientes[id].usuario);
strcat(buffer, " ha abandonado en el chat.");
bzero(vectorClientes[id].usuario, MAXLINE);
for(i = 0; i < clientes; i++)
if (i != id && vectorClientes[i].sign_in == 1)
send(vectorClientes[i].socket,buffer,MAXLINE,0);
vectorClientes[id].sign_in = 0;
}
if(strstr(buffer, "TEXT") && !strstr(buffer, "TEXT TO") && vectorClientes[id].sign_in == 1) {
longitud = strlen(buffer);
subCadena(temp, buffer, 5, longitud-5);
//Se envía a todos menos a él mismo y al que se haya ido
bzero(buffer, MAXLINE);
strcat(buffer, vectorClientes[id].usuario);
strcat(buffer, " dice: ");
strcat(buffer, temp);
for(i = 0; i < clientes; i++)
if (i != id && vectorClientes[i].sign_in == 1)
send(vectorClientes[i].socket,buffer,MAXLINE,0);
}
if(strstr(buffer, "TEXT TO") && vectorClientes[id].sign_in == 1) {
//Le quitamos el TEXT TO
subCadena(nombre, buffer, 8, MAXLINE-8);
//Nos quedamos sólo con el nombre, quitando desde el primer espacio en blanco hasta el final
strtok(nombre," ");
//Se obtiene el socket destino
destino = buscarCliente(nombre);
longitud=strlen(nombre);
strcpy(nombre, vectorClientes[id].usuario);
strcat(nombre, " dice: ");
//Recortamos el TEXT TO, el nombre, y los dos espacios hasta el mensaje(se suma solo uno (un espacio)
//porque empieza a recorrer longitud(instruccion)+longitud(nombre) desde la pos. 0 de la cadena.
subCadena(temp, buffer, 8+longitud+1, MAXLINE-(8+longitud+1));
strcat(nombre, temp);
if(destino != -1)
send(destino, nombre, MAXLINE, 0);
}
fflush(stdout);
}
close(vectorClientes[id].socket);
}
Cliente
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
| #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <string.h>
#define SERVER_PORT 6543
#define SERVER_ADDRESS "127.0.0.1"
#define MAXLINE 512
void* recibir(void* p);
void* enviar(void* p);
int main()
{
struct sockaddr_in addr;
int sd,status;
pthread_t hilos[2];
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(SERVER_ADDRESS);
addr.sin_port = htons(SERVER_PORT);
if((sd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
{
printf("Error al crear el socket\n");
exit(0);
}
if(connect(sd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
{
printf("Error al conectar\n");
exit(0);
}
else
{
if ( (status = pthread_create(&hilos[0],NULL,recibir,(void*)&sd)) )
{
printf("Error al crear hilo para recibir\n");
close(sd);
exit(0);
}
if ( (status = pthread_create(&hilos[1],NULL,enviar,(void*)&sd)) )
{
printf("Error al crear hilo para enviar\n");
close(sd);
exit(0);
}
pthread_join(hilos[0],NULL);
pthread_join(hilos[1],NULL);
}
return 1;
}
void* recibir(void* p)
{
int* id;
char buffer[MAXLINE];
id = (int*) p;
while(1)
{
recv(*id,buffer,MAXLINE,0);
printf("%s\n",buffer);
fflush(stdout);
}
}
void* enviar(void* p)
{
int* id;
char buffer[MAXLINE];
id = (int*) p;
while(1)
{
printf("\tIntroduce el mensaje\n-> ");
fgets(buffer , MAXLINE , stdin);
strtok(buffer,"\n");
send(*id,buffer,MAXLINE,0);
sleep(3);
}
} |
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <string.h>
#define SERVER_PORT 6543
#define SERVER_ADDRESS "127.0.0.1"
#define MAXLINE 512
void* recibir(void* p);
void* enviar(void* p);
int main()
{
struct sockaddr_in addr;
int sd,status;
pthread_t hilos[2];
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(SERVER_ADDRESS);
addr.sin_port = htons(SERVER_PORT);
if((sd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
{
printf("Error al crear el socket\n");
exit(0);
}
if(connect(sd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
{
printf("Error al conectar\n");
exit(0);
}
else
{
if ( (status = pthread_create(&hilos[0],NULL,recibir,(void*)&sd)) )
{
printf("Error al crear hilo para recibir\n");
close(sd);
exit(0);
}
if ( (status = pthread_create(&hilos[1],NULL,enviar,(void*)&sd)) )
{
printf("Error al crear hilo para enviar\n");
close(sd);
exit(0);
}
pthread_join(hilos[0],NULL);
pthread_join(hilos[1],NULL);
}
return 1;
}
void* recibir(void* p)
{
int* id;
char buffer[MAXLINE];
id = (int*) p;
while(1)
{
recv(*id,buffer,MAXLINE,0);
printf("%s\n",buffer);
fflush(stdout);
}
}
void* enviar(void* p)
{
int* id;
char buffer[MAXLINE];
id = (int*) p;
while(1)
{
printf("\tIntroduce el mensaje\n-> ");
fgets(buffer , MAXLINE , stdin);
strtok(buffer,"\n");
send(*id,buffer,MAXLINE,0);
sleep(3);
}
}
En Python
Servidor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
| #!/usr/bin/python
# -*- coding: utf-8 -*-
#Servidor
import string
import threading
import socket
clientes = {'nombre':[], 'socket':[]}
class gestionaClientes(threading.Thread):
def __init__(self, socket):
threading.Thread.__init__(self)
self.conn = socket
self.conectado = False
self.data = ''
def run(self):
while True:
self.data = self.conn.recv( 1024 )
if 'ADD' in self.data:
#Busca si ya ha sido insertado
if(self.conectado == False):
self.conectado = True
clientes['nombre'].append(self.data[4:])
clientes['socket'].append(self.conn)
for i in clientes['socket']:
if i != self.conn:
i.send(self.data[4:]+" ha entrado en el chat.")
else:
self.conn.send("Ya estás en el chat.")
print clientes
if ('LIST' in self.data) and (self.conectado == True):
for i in clientes['nombre']:
print "enviado a "+str(self.conn)+" "+str(i)
self.conn.send(i+" ")
print clientes
if ('END' in self.data):
if (self.conectado == True):
for i in clientes['socket']:
if i == self.conn:
nombre = clientes['nombre'][clientes['socket'].index(i)]
clientes['nombre'].remove(nombre)
clientes['socket'].remove(i)
self.conectado = False
for i in clientes['socket']:
if i != self.conn:
i.send(nombre+" ha salido del chat.")
self.conn.send(" ")
else:
self.conn.send(" ")
if ('TEXT' in self.data and 'TEXT TO' not in self.data) and (self.conectado == True):
for i in clientes['socket']:
if i != self.conn:
i.send(clientes['nombre'][clientes['socket'].index(self.conn)]+" dice: "+self.data[5:])
print clientes
if ('TEXT TO' in self.data) and (self.conectado == True):
palabras = self.data[8:].split()
#busca si existe alguien con ese alias
for i in clientes['nombre']:
if i == palabras[0]:
#Prepara el mensaje
del palabras[0]
mensaje = string.join(palabras, ' ')
clientes['socket'][clientes['nombre'].index(i)].send(clientes['nombre'][clientes['socket'].index(self.conn)]+" dice: "+mensaje)
self.conn.close()
#creamos socket pasivo y escuchamos en el puerto 9000
s = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
s.bind( ( socket.gethostname(), 9000 ) )
s.listen( 5 )
while(True):
conn, addr = s.accept()
gestionaClientes(conn).start() |
#!/usr/bin/python
# -*- coding: utf-8 -*-
#Servidor
import string
import threading
import socket
clientes = {'nombre':[], 'socket':[]}
class gestionaClientes(threading.Thread):
def __init__(self, socket):
threading.Thread.__init__(self)
self.conn = socket
self.conectado = False
self.data = ''
def run(self):
while True:
self.data = self.conn.recv( 1024 )
if 'ADD' in self.data:
#Busca si ya ha sido insertado
if(self.conectado == False):
self.conectado = True
clientes['nombre'].append(self.data[4:])
clientes['socket'].append(self.conn)
for i in clientes['socket']:
if i != self.conn:
i.send(self.data[4:]+" ha entrado en el chat.")
else:
self.conn.send("Ya estás en el chat.")
print clientes
if ('LIST' in self.data) and (self.conectado == True):
for i in clientes['nombre']:
print "enviado a "+str(self.conn)+" "+str(i)
self.conn.send(i+" ")
print clientes
if ('END' in self.data):
if (self.conectado == True):
for i in clientes['socket']:
if i == self.conn:
nombre = clientes['nombre'][clientes['socket'].index(i)]
clientes['nombre'].remove(nombre)
clientes['socket'].remove(i)
self.conectado = False
for i in clientes['socket']:
if i != self.conn:
i.send(nombre+" ha salido del chat.")
self.conn.send(" ")
else:
self.conn.send(" ")
if ('TEXT' in self.data and 'TEXT TO' not in self.data) and (self.conectado == True):
for i in clientes['socket']:
if i != self.conn:
i.send(clientes['nombre'][clientes['socket'].index(self.conn)]+" dice: "+self.data[5:])
print clientes
if ('TEXT TO' in self.data) and (self.conectado == True):
palabras = self.data[8:].split()
#busca si existe alguien con ese alias
for i in clientes['nombre']:
if i == palabras[0]:
#Prepara el mensaje
del palabras[0]
mensaje = string.join(palabras, ' ')
clientes['socket'][clientes['nombre'].index(i)].send(clientes['nombre'][clientes['socket'].index(self.conn)]+" dice: "+mensaje)
self.conn.close()
#creamos socket pasivo y escuchamos en el puerto 9000
s = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
s.bind( ( socket.gethostname(), 9000 ) )
s.listen( 5 )
while(True):
conn, addr = s.accept()
gestionaClientes(conn).start()
Cliente
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
| #!/usr/bin/python
# -*- coding: utf-8 -*-
#Cliente
from Tkinter import *
import threading
import socket
class App:
def __init__(self, master, socket):
self.conn = socket
self.frame = Frame(master)
self.label = Label(self.frame, text="Cliente chat. Python+TkInter. David López")
self.textarea = Text(self.frame, height=20, width=40)
self.scroll = Scrollbar(self.frame, command=self.textarea.yview)
self.textarea.configure(yscrollcommand=self.scroll.set)
self.texto_enviar = StringVar()
self.text_ent = Entry(self.frame, textvariable=self.texto_enviar)
self.btn_enviar = Button(self.frame, text="Enviar", command=self.enviar)
self.btn_salir = Button(self.frame, text="Salir", command=self.salir)
self.frame.grid()
self.label.grid(row=0, column=0, columnspan=3)
self.textarea.grid(row=1, column=0, columnspan=2)
self.scroll.grid(row=1, column=2, sticky=N+S)
self.text_ent.grid(row=2, column=0, columnspan=2, sticky=W+E)
self.btn_enviar.grid(row=3, column=0)
self.btn_salir.grid(row=3, column=1)
def enviar(self):
self.conn.send(self.text_ent.get())
self.text_ent.delete(0, END)
# Esta es una función de retrollamada.
def salir(self):
lee.parar()
self.conn.send("END")
self.frame.quit()
def escribir(self, texto):
self.textarea.insert(END, texto)
class leer(threading.Thread):
def __init__(self, socket):
threading.Thread.__init__(self)
self.mensaje = ''
self.conn = socket
self.stop = False
def run(self):
while (self.stop == False):
self.mensaje = self.conn.recv( 1024 )
app.escribir(self.mensaje+'\n')
self.conn.close()
def parar(self):
self.stop = True
miSocket = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
miSocket.connect( (socket.gethostname(), 9000 ) )
lee = leer(miSocket)
lee.start()
root = Tk()
root.title('Chat Python-TkInter - David López')
app = App(root, miSocket)
root.mainloop() |
#!/usr/bin/python
# -*- coding: utf-8 -*-
#Cliente
from Tkinter import *
import threading
import socket
class App:
def __init__(self, master, socket):
self.conn = socket
self.frame = Frame(master)
self.label = Label(self.frame, text="Cliente chat. Python+TkInter. David López")
self.textarea = Text(self.frame, height=20, width=40)
self.scroll = Scrollbar(self.frame, command=self.textarea.yview)
self.textarea.configure(yscrollcommand=self.scroll.set)
self.texto_enviar = StringVar()
self.text_ent = Entry(self.frame, textvariable=self.texto_enviar)
self.btn_enviar = Button(self.frame, text="Enviar", command=self.enviar)
self.btn_salir = Button(self.frame, text="Salir", command=self.salir)
self.frame.grid()
self.label.grid(row=0, column=0, columnspan=3)
self.textarea.grid(row=1, column=0, columnspan=2)
self.scroll.grid(row=1, column=2, sticky=N+S)
self.text_ent.grid(row=2, column=0, columnspan=2, sticky=W+E)
self.btn_enviar.grid(row=3, column=0)
self.btn_salir.grid(row=3, column=1)
def enviar(self):
self.conn.send(self.text_ent.get())
self.text_ent.delete(0, END)
# Esta es una función de retrollamada.
def salir(self):
lee.parar()
self.conn.send("END")
self.frame.quit()
def escribir(self, texto):
self.textarea.insert(END, texto)
class leer(threading.Thread):
def __init__(self, socket):
threading.Thread.__init__(self)
self.mensaje = ''
self.conn = socket
self.stop = False
def run(self):
while (self.stop == False):
self.mensaje = self.conn.recv( 1024 )
app.escribir(self.mensaje+'\n')
self.conn.close()
def parar(self):
self.stop = True
miSocket = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
miSocket.connect( (socket.gethostname(), 9000 ) )
lee = leer(miSocket)
lee.start()
root = Tk()
root.title('Chat Python-TkInter - David López')
app = App(root, miSocket)
root.mainloop()