MV Coders on fire

Nucklear

#120 TY, asi tengo algo para guiarme que ando perdido jeje

1 respuesta
Khanser

#121 Aparte de eso búscate algún librito sobre paralelismo y concurrencia, que te hará falta, sino tendrás problemas con corrupción de datos cuando intentes leer y escribir la misma variable desde hilos diferentes :)

elkaoD

#120 qué sincronización ni qué ostias? xD

Lo más complicado de hacerlo asíncrono es que los sockets no sean bloqueantes. Del resto se encarga TCP y es tan simple como, en el momento en el que un cliente manda una frase, reenviarla al resto. Fin. No hay nada que sincronizar.

1 respuesta
EnZo

#120 Es que te equivocas. En ningun caso es una conexion asincrona. Ni con tu modelo ni con el mio puede serlo.

#119 Y si te gusta php, hay infinitos ejemplos por google:
https://www.google.es/search?q=socket+server+php&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:es-ES:official&client=firefox-a

1 respuesta
Khanser

#123 Pero imagino que no en todos los lenguajes puedes evitar que se bloquee la recepción de paquetes. Y debes tener claro por qué estas configurando tu recepción de paquetes TCP para que no bloquee el hilo no? Claro que el que se encuentre una recepción de paquetes no bloqueante y le funcione gracias al buffer de los datos que ha ido almacenando por detras se pensará que todo es mágico, pero la idea con todo esto es aprender, y el que se encuentre con que su api es bloqueante por defecto, no va a saber por qué su ventanita no tira hasta que recibe datos por red.

#124 wtf?

Por favor, me gustaría aclarar que no estoy discutiendo para ver quien tiene la polla más grande, me pongo en la piel del pobre chaval que está leyendo esta discusión sin haber hecho NUNCA un envío/recepción de paquetes por red y ya está dudando si intentar programar en esta Kata.

1 respuesta
B

#125: Con Java y al menos que me equivoque, no tienes que saber NADA de paralelismo ni concurrencia (no sé con otros lenguajes).

PD: Con que lea tres páginas de teoría de sockets (yo mismo puedo colgar unos de mi facultad para Java), lo hace de sobra. Es decir, una vez que eres capaz de hacer un echo-server, lo demás ya es lógica muy sencilla.

Pero ese problema lo va a tener con cualquier modelo.

PD2: Ten en cuenta que no vas a guardar mensajes en el servidor ni nada eh? O vamos esa no era mi idea.

1 respuesta
Khanser

#126 Bueno claro, le enchufamos synchronized a todas las clases, metodos y metemos todas nuestras operaciones en bloques synchronized y ya somos Sync masters no? XD
En java igual que en otros lenguajes tendrás problemas de sincronización si no usas las estructuras de datos adecuadas entre Threads y realizas las lecturas de atributos mediante metodos synchronized adecuadamente. Que es más facil y no te tienes que meter con mutex, y en caso de procesos con memoria compartida y semaforos? Pues vale, te doy la razón, con Java es más sencillo, pero si no sabes lo que haces la vas a acabar cagando igual xD

#126 PD2:En el server, como dicen por arriba, se ponen los soquets en no bloqueantes, y vas leyendo del buffer. Pero en según que otros lenguajes con segun que GUI, si no separas la vista de la recepción, se te va a clavar la ventanita hasta k no recibas datos (nuevamente si no has puesto los soquets en no bloqueantes)

2 respuestas
B

#127: No me estás entiendiendo. No estoy hablando de usar synchronized en NADA.

Te estoy hablando de que tu tienes una serie de sockets abiertos según los clientes que tengas. Que entra un cliente nuevo? Broadcast a los demás notificándolo. Que manda un mensaje? Igual.

No hay absolutamente nada que pueda bloquearse excepto la lista de sockets creo. Y en cualquier caso en tu idea pasa lo mismo xD

PD: Y si se te bloquea la GUI es porque lo estás haciendo mal. GUI y recepción de datos en el mismo thread? Nunca.

PD2: De todas formas no sé por qué te estás poniendo tan violento xD (porque eres solo tu además).

Si quieres lo hacemos a tu manera, yo no tengo ningún inconveniente.

1
elkaoD

#127 como dice oip es más complicada la concurrencia con tu idea que simplemente haciendo broadcast. Lo fácil es el broadcast, que NO necesita controlar accesos sincronizados ni nada.

Khanser

Parece que a todos os gusta un sistema de servidor que vaya replicando los mensajes de los clientes, y las incorporaciones y despedidas del chat, así que lo haremos así.

Ahora necesitamos una propuesta de protocolo de comunicación, ya tenemos claro que será por TCP mediante cadenas de texto. Gogogo!

B

fu, yo no tengo ni idea de como programar esto, para el 30 dudo que esté xDDD. Pero me interesa e intentaré hacer algo.

Sobre el protocolo como veáis, no me meto.

1 1 respuesta
B

#131: Una vez que sabes utilizar sockets (es muy sencillito a nivel básico). Es solo recoger mensajes y elaborar respuestas.

Ejemplo: http://introcs.cs.princeton.edu/java/84network/EchoServer.java.html

#132, #133: Claro, en local todo. 127.0.0.1

1 1 respuesta
B

#132 ah pues sockets sé usar en java y C... :) pero necesito montar un servidor con IP fija o DNS, ¿no? ¿o no hace falta? Perdón por las preguntas tontas xD

4 respuestas
Nucklear

#133 Supongo que si usas tu ip local como host y el cliente en el mismo pc no tienes problema.

1 1 respuesta
Khanser

#133 #134 Lo único que debeis tener en cuenta es que el socketserver del servidor y el socketserver del cliente los teneis que abrir en diferentes puertos en la misma máquina, pero no tendreis problema teniendo server y cliente en la misma máquina

2 respuestas
Nucklear

#135 Bueno yo he hecho la prueba mirando lo que me pasaste en #120, el tema es básicamente lo que estuve probando también con un bot para IRC. El código lo dejo aquó comentando cada línea del lado del servidor para que pueda echarle un ojo #133:

Servidor:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import socket

#Creamos nuevo socket
conexion = socket.socket()

#Indicamos la tupla host/puerto de conexion
conexion.bind(("127.0.0.1", 9999))

#Invocamos el listener pasando el numero maximo de conexiones
conexion.listen(10)

#El metodo accept nos devuelve un nuevo socket con el que enviar/recibir peticiones
#y la direccion final de conexion.
sc, dir = conexion.accept()

#Confirmacion de la conexion del cliente
print "Soy el servidor y he recibido una conexion de " + str(dir[0]) + ":" + str(dir[1])

while True:
    #Creamos el buffer con un tamaño maximo de 1024 bytes
    buffer = sc.recv(1024)
    
#Si el string recibido es "disconnect" paramos el servidor if buffer == "disconnect": break print "Recibido:" + buffer #Enviamos la respuesta al cliente sc.send("Test completado, tu servidor funciona correctamente") sc.close() conexion.close()

Cliente:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import socket


conexion = socket.socket()

conexion.connect(("127.0.0.1", 9999))

while True:
    mensaje = raw_input("Escribe el mensaje a enviar: ")
    
conexion.send(mensaje) if mensaje == "disconnect": print "Hasta la próxima" break buffer = conexion.recv(1024) print "Has recibido: " + buffer conexion.close()

He puesto el mísmo puerto en ambos y no me da error o.O

2 respuestas
elkaoD

#135 el cliente no debe usar ServerSocket así que da completamente igual en qué puerto bindée porque... no bindea a ningún puerto (bindea a un socket interno en la pila TCP/IP y fin, ni te enteras.)

#136 lo raro sería tener puerto diferente xD El puerto del cliente es hacia cuál se conecta DEL SERVIDOR. No es el puerto del cliente.

2 respuestas
B

#136 no si ahora ya lo he pillado, thx... Es que estaba pensando en un chat en plan hablando todos los del hilo y digo, de dónde saco yo ahora el servidor xDD. En fin, que estoy espeso... Muchas gracias por pensar en mí :qq:

Nucklear

#137 Vale si obvio xD me merezco una colleja si tengo el listener en ese puerto no voy a apuntar a otro...

Khanser

#137 Vale, right, con tcp y los streams de salida y entrada no hacía falta bindear en cliente, fallo mio xD

B

Vale, pero seguimos sin tener definido un protocolo global.

A ver, incluso estaría divertido que cada uno hiciese su protocolo. Así también podemos comprobar eso (ya hemos visto que tenemos diferentes opiniones). Total, lo de interconectarlos mola, pero tampoco es para tanto xD

Yo voy a hacer el servidor en C y el cliente en Python posiblemente. En cuanto al servidor, efectivamente Khanser tenía razón (te pido disculpas, porque no me había dado cuenta xD), y a la lista de nicks hay que acceder con cuidado. Pero bueno, un mutex y "al carallo".

#142: Eso como queráis. A mí me da igual el protocolo, pero pienso ponerme entre hoy y mañana y si lo cambiáis paso de vosotros y hago el oip's protocol xDDD.

El tema de la concurrencia en C a nivel básico es muy sencillo (aunque me gustaría que me confirmase otro, no soy bueno en C). Léete sobre mutex, son unas "variables" que vas bloqueando y desbloqueando.

Por ejemplo, me conecto como oip mandando un mensaje. Entonces el servidor recibe la petición y comprueba si el mutex está ocupado, como no lo está lo bloquea y se pone a dar de alta el nick.

Justo entonces llegas tu, se comprueba el mutex y se ve que está bloqueado, entonces hay que esperar.

Vamos, es algo así como:

while(mutexNotBusy) {
    //wait
}

write_list(nick);
4 respuestas
B

#141 Las funcionalidades usamos las tres primeras de #116 no?

Y otra cosa, alguna guía para concurrencia en C? Porque yo he hecho en java, pero prefiero programar en C (y quizás el cliente en Perl).
#141 sí pero por poner un ejemplo: en java el mutex necesitaba declarar mutexNotBusy como volatile porque sino me bloqueaba el proceso el while, y en general espera activa no era precisamente lo mejor del mundo... Además no sé qué me dijeron de los semáforos en C y el POSIX, aunque no creo que aquí aplique. Por eso digo a lo mejor hay algún manual o algo...

1 respuesta
A

Cuidado con la sincronización de hilos en C/C++. No viene implementado de serie en el lenguaje y hay que adoptar standards no coincidentes. POSIX no lo implementa Windows (o no entero), y Win32 no lo implementa Unix.
Con POSIX puedes usar mutex o semáforos de toda la vida, y con win32 las CRITICAL_SECTION vas sobrado, pero claro... esto ya se va de lo que es el problema.
En este aspecto yo iría hacia standares más abiertos como Boost (boost::mutex:: ). Es lo más elegante y lo más libre de arquitecturas, pero Boost es una librería considerable y no apta para iniciados en C++, con lo que se sale bastante del ámbito del ejercicio, a mi juicio.

En otros lenguajes que tengan estas estructuras integradas es mucho más sencillo, pero C++ es chulo chulo como mi pirulo y es lo que toca.

Un saludo, gente!

PD: Evitar esperas activas, que son sucias xD. Los mutex tienen funciones de lock() y unlock() que se encargan de esperar, meter a los hilos en listas de captura y demás.

1 respuesta
B

#143 justo estaba mirando lo del POSIX y sí, tienes razón. Creo que no lo haré en C xD, haré todo Perl.

EnZo

#141 Yo voto por un protocolo general para todos. Y así podremos usar los clientes para conectar a cualquier server. Incluso podriamos hacer pruebas de rendimiento.

EnZo

Empiezo yo, vamos construyendolo entre todos si quieres.

<- (Entrada) El cliente recibe
-> (Salida) El cliente envia

  • Listado de usuarios conectados
    -> L:
    <- L:User1:User2:User3

  • Setear tu nick una vez conectado
    -> N:EnZo

  • Alguien ha cambiado de nick
    <- N:EnZo:NewNick

  • Alguien entra/conecta
    <- J:User

  • Alguien sale/desconecta
    <- X:User

  • Mensajes para la sala
    -> M:tu mensaje en cuestion
    <- M:User:el mensaje de user

  • Mensajes privados
    -> P:User:tu mensaje en cuestion
    <- P:User:el mensaje de user

  • Errores
    <- E:125

Es muy importante definir si vamos a crear salas/canales o no, porque cambia drasticamente el protocolo.
Los nicks deben ser case sensitive y no pueden contener el caracter :

2 respuestas
B

#146 En nick también faltaría

*El nick está usado
<- N:EnZo:NickUsed

¿no?
ok, iría en errores ?

Luego, configurar el nick puede ser el mismo mensaje estés conectado o te estés intentando conectar... La conexión debería contener simplemente N:EnZo y si usamos canales pues N:EnZo:C:MVPro-gramer

1 respuesta
EnZo

#147 Yo eso lo contemplo como un mensaje de error. E:2 por ejemplo. Pero como tu dices tambien se puede hacer.

1 respuesta
B

#148 nono, estoy de acuerdo contigo, es más limpio así (aunque quizás menos userfriendly pero eso da igual xD). Yo tal como está lo veo bien, si acaso lo de los canales pero para mí ahora mismo no es imprescindible.

Khanser

#141 Gracias, era lo que intentaba dar a entender desde la página 4.

Habría que definir si usar carácteres de 1 byte, o unicode de 2 bytes. Para hacerlo internacional lo suyo sería cadenas de carácteres de 2 bytes.

Me quedo con el protocolo de #146, pero además propondría que el server siempre responda si todo ha ido bien o no y además, que en el OK del comando "J" Join, te devuelva la lista de usuarios conectados en ese momento.

Además podríamos ir definiendo los mensajes de error:

  • Error 1: Nick ya existente

  • Error 2: Operación no permitida (intentar mandar mensaje, o privado sin haber entrado antes)

  • Error 2: Flood error, demasiados comandos en poco tiempo, lo suyo sería 1 op cada 100 ms +o-

  • Moar¿?¿

1 respuesta