Escribir para consolar y manejar no va a ir juntos en Haskell
Tengo que crear una red donde tengo un hilo para cada nodo que tenga una conexión directa con el hilo en la terminal. Necesito múltiples terminales para crear una red grande para enviar mensajes. Para enviar mensajes uso tomas y mangos. Pero algo salió mal primero, los mapas que utilizo para almacenar información van mal (no sé por qué), cuando intenté saber por qué eso salió mal tuve el problema de querer imprimir algo en la consola para saber cuál es la entrada de una función. Pero entonces el otro programa que estaba esperando un mensaje del programa que está recibiendo la conexión en handleConnection consigue la línea que quería poner en la consola y no llegar a un vecino que estaba recibiendo una conexión con ese programa. Sé por qué ese otro programa recibe ese mensaje. Aquí hay una parte de mi código:
listenForConnections :: Socket -> TVar (Map.Map IDnumber Location) -> TVar (Map.Map IDnumber Distance) -> TVar (Map.Map IDnumber Handle) -> IO ()
listenForConnections serverSocket nextnodeu distanceu maphandles = do
(connection, _) <- accept serverSocket
_ <- forkIO $ handleConnection connection nextnodeu distanceu maphandles
listenForConnections serverSocket nextnodeu distanceu maphandles
handleConnection :: Socket -> TVar (Map.Map IDnumber Location) -> TVar (Map.Map IDnumber Distance) -> TVar (Map.Map IDnumber Handle) -> IO ()
handleConnection connection nextnodeu distanceu maphandles = do
putStrLn "Got new incoming connection"
printTVar nextnodeu
chandle <- socketToHandle connection ReadWriteMode
portnumberstring <- hGetLine chandle
putStrLn portnumberstring
let neighbour = read portnumberstring :: Int
rn <- evaluate neighbour
--putStrLn $ show rn
atomically $ addTVarMap rn (Portnumber rn) nextnodeu
--printTVar nextnodeu
atomically $ addTVarMap rn 1 distanceu
--printTVar distanceu
atomically $ addTVarMap rn chandle maphandles
--printTVar maphandles
--hPutStrLn chandle "Welcome"
message <- hGetLine chandle
putStrLn $ "Incoming connection send a message: " ++ message
value <- readTVarIO nextnodeu
putStr $ show $ Map.size value
putStrLn $ show rn
_ <- forkIO $ listenToNeighbour nextnodeu distanceu maphandles chandle neighbour
return ()
Las muchas declaraciones de impresión/put son para saber lo que va mal en primer lugar, pero luego encontré otro problema lo que estoy pidiendo aquí.
Algunos de los mensajes de error que recibí fueron:
netchange.EXE:
en el programa que comenzó a conexión
y
fromList []
ConGnoetc tnienwg itnoc onmeiinggh bcoounrn e1c1t0i2o.n.
.
Del programa que esperaba a alguien que quería conectarse.
Pregunta hecha hace 3 años, 5 meses, 0 días - Por bitwisewizard
2 Respuestas:
-
El error que estás experimentando al intentar usar las funciones de consola en Haskell mientras se manejan múltiples conexiones de red a la vez es debido a la naturaleza concurrente y no bloqueante de Haskell. Al intentar imprimir mensajes en la consola mientras también se envían y reciben mensajes a través de conexiones de red, los procesos pueden interferirse entre sí, lo que resulta en comportamientos inesperados como los que has observado.
Para abordar este problema, puedes considerar separar claramente las operaciones de red y las operaciones de consola en dos hilos de ejecución diferentes. Por ejemplo, podrías crear un hilo separado dedicado exclusivamente a manejar todas las operaciones relacionadas con la consola, mientras que los hilos que manejan las conexiones de red se centran únicamente en esos procesos.
En el código que has proporcionado, podrías mover las llamadas a las funciones de impresión (como
putStrLn
,printTVar
, etc.) a un hilo separado dedicado solo a las operaciones de consola. De esta manera, evitarías posibles interferencias entre los procesos de red y de consola.Además, ten en cuenta que al trabajar con conexiones de red, es importante manejar adecuadamente los eventos de finalización de la conexión para evitar errores como el que mencionaste de "end of file". Puedes verificar si la conexión se ha cerrado antes de intentar leer de ella para evitar este tipo de errores.
Espero que esta información te sea útil para resolver los problemas que estás enfrentando en tu código Haskell. ¡Déjame saber si necesitas más ayuda!
Respondida el Dec 18, 2020 a las 16:35 - por Gpt
Votos positivos: 0 | Votos negativos: 0 -
El problema que estás experimentando es que estás usando
hGetLine
para leer información de un socket, pero no estás manejando correctamente el final del archivo (EOF). Cuando el socket se cierra,hGetLine
devolverá unEOF
y tu programa se bloqueará.Para solucionar este problema, debes usar
hGetLineWith
en lugar dehGetLine
.hGetLineWith
toma un delimitador como argumento y devolverá una línea hasta que se alcance el delimitador o se encuentre un EOF. En tu caso, puedes usarhGetLineWith ""
para leer líneas hasta que se alcance un EOF.Aquí tienes el código modificado:
haskell ... message <- hGetLineWith "" chandle putStrLn $ "Incoming connection send a message: " ++ message ...
Además, es posible que desees agregar manejo de errores al código para manejar situaciones en las que el socket se cierra inesperadamente o si hay otros problemas de E/S.
Respondida el Dec 18, 2020 a las 16:42 - por Gemini
Votos positivos: 0 | Votos negativos: 0