Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sockets Haskell中的套接字编程:putStrLn/hPutStrLn未按预期运行_Sockets_Haskell_Io - Fatal编程技术网

Sockets Haskell中的套接字编程:putStrLn/hPutStrLn未按预期运行

Sockets Haskell中的套接字编程:putStrLn/hPutStrLn未按预期运行,sockets,haskell,io,Sockets,Haskell,Io,我目前正试图用Haskell编写一个toy服务器,以at为例作为套接字编程的基准 我遇到了一个问题,putStrLn和hPutStrLn的行为与我预期的不一样。本文底部的代码是一个完整的示例,演示了我的问题,编译和运行时没有问题,如下所示: sanitizeInput :: Handle -> IO String sanitizeInput handle = do input <- hGetLine handle return (sanitize input) ba

我目前正试图用Haskell编写一个toy服务器,以at为例作为套接字编程的基准

我遇到了一个问题,
putStrLn
hPutStrLn
的行为与我预期的不一样。本文底部的代码是一个完整的示例,演示了我的问题,编译和运行时没有问题,如下所示:

sanitizeInput :: Handle -> IO String
sanitizeInput handle = do
    input <- hGetLine handle
    return (sanitize input)

badChars :: [Char]
badChars = ['\r']

sanitize :: String -> String
sanitize = filter (\x -> not (elem x badChars))
$ghc-main是TestServer.main TestServer.hs

$。/TestServer

服务器在端口4242上接受telnet连接,如下所示:

sanitizeInput :: Handle -> IO String
sanitizeInput handle = do
    input <- hGetLine handle
    return (sanitize input)

badChars :: [Char]
badChars = ['\r']

sanitize :: String -> String
sanitize = filter (\x -> not (elem x badChars))
$telnet localhost 4242

然后它会提示用户输入他们的姓名。输入后,用户应收到以下消息:

欢迎,[用户名]

而是接收信息

!!elcome,[用户名]

请注意,感叹号似乎从字符串末尾移动,并替换“W”。用户名的长度没有区别,结果是一样的

此外,运行服务器的终端应显示用户名称,如下所示:

sanitizeInput :: Handle -> IO String
sanitizeInput handle = do
    input <- hGetLine handle
    return (sanitize input)

badChars :: [Char]
badChars = ['\r']

sanitize :: String -> String
sanitize = filter (\x -> not (elem x badChars))
[用户名]已加入服务器

而是显示:

已加入服务器

用户名似乎是空字符串。但是,如果我们简单地替换这条线

putStrLn(用户名newUser)

排队

putStrLn((userName newUser)++“已加入服务器”)

用户名显示正确。我有点不明白为什么会出现这些问题(上面链接的示例编译得很好,putStrLn/hPutStrLn没有这样的问题。我确信这是一个非常微妙的问题

以下是上述代码:

-- TestServer.hs
module TestServer where

import Control.Concurrent
import Network.Socket
import System.IO

type User = (Handle, String)

userName :: User -> String
userName (_, name) = name

main :: IO ()
main = do
    sock <- socket AF_INET Stream 0
    setSocketOption sock ReuseAddr 1
    bind sock (SockAddrInet 4242 iNADDR_ANY)
    listen sock 2
    socketLoop sock []

socketLoop sock users = do
    (uSock, _)      <- accept sock
    uHandle         <- socketToHandle uSock ReadWriteMode
    hSetBuffering uHandle NoBuffering
    newUser         <- initUser uHandle

    putStrLn ((userName newUser) ++ " has joined the server.")

    socketLoop sock (newUser:users)

initUser :: Handle -> IO User
initUser handle = do
    hPutStr handle "Please enter your name: "
    name <- hGetLine handle
    let user = (handle, name) in do
        hPutStrLn handle ("Welcome, " ++ name ++ "!")
        return user
--TestServer.hs
模块TestServer在哪里
导入控制。并发
导入网络套接字
导入系统.IO
类型User=(句柄,字符串)
用户名::用户->字符串
用户名(_,name)=名称
main::IO()
main=do

sock我将该问题标记为重复问题,但我想发布从该问题得出的解决方案,以防证明它可能有用,因为原始问题不包含明确的解决方案

我将对
hGetLineHandle
的调用包装如下:

sanitizeInput :: Handle -> IO String
sanitizeInput handle = do
    input <- hGetLine handle
    return (sanitize input)

badChars :: [Char]
badChars = ['\r']

sanitize :: String -> String
sanitize = filter (\x -> not (elem x badChars))
sanitizeInput::Handle->IO字符串
sanitizeInput句柄=do
输入字符串
清理=过滤器(\x->not(elem x badChars))

我几乎可以肯定你的换行符太乱了。当你在telnet提示符下按
CR
时,它会发送类似
\r\n
的信息,但是
hGetLine
只需要
\n
。因此“\r”成为用户名的一部分,所以“!”请看,谢谢,这是正确的方法。通过去掉“\r”字符来清理输入就可以了。现在,元问题是:我是否应该将其标记为dup?将我的解决方案作为我自己问题的答案发布是否有用?或者@Yuras,您是否愿意回答?仅供参考-数据。列表定义
注释lem