Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.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
什么';这台f#echo服务器出了什么问题?_F# - Fatal编程技术网

什么';这台f#echo服务器出了什么问题?

什么';这台f#echo服务器出了什么问题?,f#,F#,我写了这个f#echo服务器: open System.Net open System.Net.Sockets open System.IO open System open System.Text open System.Collections.Generic let addr = IPAddress.Parse("127.0.0.1") let listener = new TcpListener(addr, 2000) listener.Start() let rec loop2(c:

我写了这个f#echo服务器:

open System.Net
open System.Net.Sockets
open System.IO
open System
open System.Text
open System.Collections.Generic

let addr = IPAddress.Parse("127.0.0.1")
let listener = new TcpListener(addr, 2000)
listener.Start()

let rec loop2(c:TcpClient,sr:StreamReader,sw:StreamWriter)=async {
        let line=sr.ReadLine()
        if not(line=null) then
            match line with
                |"quit"->
                    sr.Close()
                    sw.Close()
                    c.Close()  
                 |_ ->
                    if line.Equals("left") then
                        sw.WriteLine("right")
                        return! loop2(c,sr,sw)
                    sw.WriteLine(line)
                    return! loop2(c,sr,sw)

        else
            sr.Close()
            sw.Close()
            c.Close()   
}

let loop()=async {
while true do
    let c=listener.AcceptTcpClient()
    let d = c.GetStream()
    let sr = new StreamReader(d)
    let sw = new StreamWriter(d)
    sw.AutoFlush<-true
    Async.Start(loop2(c,sr,sw))
}

Async.RunSynchronously(loop())
开放系统.Net
开放式System.Net.Sockets
开放系统
开放系统
开放系统.Text
open System.Collections.Generic
让addr=IPAddress.Parse(“127.0.0.1”)
let listener=新的TcpListener(地址,2000)
listener.Start()
让rec loop2(c:TcpClient,sr:StreamReader,sw:StreamWriter)=异步{
let line=sr.ReadLine()
如果不是(line=null),则
匹配
|“退出”->
高级关闭()
sw.Close()
c、 关闭()
|_ ->
如果line.等于(“左”),那么
西南书写线(“右”)
返回!回路2(c、sr、sw)
西南写入线(行)
返回!回路2(c、sr、sw)
其他的
高级关闭()
sw.Close()
c、 关闭()
}
let loop()=异步{
尽管如此
设c=listener.AcceptCpcClient()
设d=c.GetStream()
设sr=新的StreamReader(d)
设sw=新StreamWriter(d)

sw.AutoFlush问题在于,与命令式语言中的同名函数不同,计算表达式中的
return
不会短路。因此一旦
if line.Equals(“右”)中的
return!
返回,即在套接字关闭后,运行
if
块后的代码并尝试写入关闭的套接字。解决方法是将这两行放入
else

                if line.Equals("left") then
                    sw.WriteLine("right")
                    return! loop2(c,sr,sw)
                else
                    sw.WriteLine(line)
                    return! loop2(c,sr,sw)
作为一个附加的样式提示,整个主体可以实现为一个
匹配

let rec loop2(c:TcpClient,sr:StreamReader,sw:StreamWriter)=async {
    let line=sr.ReadLine()
    match line with
    | null | "quit" ->
        sr.Close()
        sw.Close()
        c.Close()
    | "left" ->
        sw.WriteLine("right")
        return! loop2(c,sr,sw)
    | _ ->
        sw.WriteLine(line)
        return! loop2(c,sr,sw)
}

代码中的问题如下:

if line.Equals("left") then
    sw.WriteLine("right")
    return! loop2(c,sr,sw)
sw.WriteLine(line)
return! loop2(c,sr,sw)
如果收到一个“left”,它将写入“right”,然后执行嵌套的
loop2
s,直到收到一个“quit”。然后,在所有这些都完成之后,它将尝试写入
line
,并执行更多嵌套的
loop2
s。当然,此时,您已经处理了连接,因此出现了异常

似乎写入
应该在else块中,这样可以防止错误:

if line.Equals("left") then
    sw.WriteLine("right")
else
    sw.WriteLine(line)
return! loop2(c,sr,sw)
当然,您也可以将此检查与模式匹配集成在一起。下面的示例将在一个结构中处理空检查和每个字符串选项

let line = Option.ofObj <| sr.ReadLine()
match line with
|None 
|Some("quit") -> 
    sr.Close()
    sw.Close()
|Some("left") -> 
    sw.WriteLine("right")
    return! loop2(c,sr,sw)
|Some(line) ->
    sw.WriteLine(line)
    return! loop2(c,sr,sw)
然后,您可以创建一个正确的异步版本:

let rec handleClient (c:TcpClient) (sr:StreamReader) (sw:StreamWriter) =
    async {
        let! line = readLineAsync sr
        match Option.ofObj(line) with
        |None 
        |Some("quit")-> 
            sr.Close()
            sw.Close()
        |Some("left") -> 
            do! writeLineAsync sw "right"
            return! loop2(c,sr,sw)
        |Some(line) ->
            do! writeLineAsync sw line
            return! loop2(c,sr,sw)
    }

let loop() = 
    async {
        let! c = acceptClientAsync listener
        let sr = new StreamReader(c.GetStream())
        let sw = new StreamWriter(c.GetStream())
        sw.AutoFlush <- true
        do! handleClient c sr sw |> Async.StartChild |> Async.Ignore
        return! loop()
    }
让rec处理客户端(c:TcpClient)(sr:StreamReader)(sw:StreamWriter)=
异步的{
让!line=readLineAsync sr
将选项ofObj(行)与匹配
|没有
|一些(“退出”)->
高级关闭()
sw.Close()
|一些(“左”)->
做!写下EasySync sw“正确”
返回!回路2(c、sr、sw)
|一些(行)->
执行!写入EASYNC sw行
返回!回路2(c、sr、sw)
}
让循环()
异步的{
let!c=acceptClientAsync侦听器
设sr=newstreamreader(c.GetStream())
设sw=newstreamwriter(c.GetStream())
sw.AutoFlush Async.StartChild |>Async.Ignore
return!loop()
}

您得到的异常是什么?您能将该信息添加到您的问题中吗?请将异常复制并粘贴到问题中,而不是使用屏幕截图。异常的屏幕截图不允许任何人通过谷歌搜索异常文本,因此帮助不大。另外,请让我们查看异常的整个堆栈跟踪,而不是just位于第一行。查看stacktrace的其余部分可能会提供一些线索,帮助用户找出导致异常的原因。
let rec handleClient (c:TcpClient) (sr:StreamReader) (sw:StreamWriter) =
    async {
        let! line = readLineAsync sr
        match Option.ofObj(line) with
        |None 
        |Some("quit")-> 
            sr.Close()
            sw.Close()
        |Some("left") -> 
            do! writeLineAsync sw "right"
            return! loop2(c,sr,sw)
        |Some(line) ->
            do! writeLineAsync sw line
            return! loop2(c,sr,sw)
    }

let loop() = 
    async {
        let! c = acceptClientAsync listener
        let sr = new StreamReader(c.GetStream())
        let sw = new StreamWriter(c.GetStream())
        sw.AutoFlush <- true
        do! handleClient c sr sw |> Async.StartChild |> Async.Ignore
        return! loop()
    }