.net Tcplistener随机重置连接
我正在玩一个用F#编写的简单Web服务器。正如我所注意到的,如果我在Firefox中点击refresh,经过一些尝试后,我会看到一个错误页面,上面写着: 连接已重置 加载页面时已重置与服务器的连接 为什么这看起来是随机发生的(将待办事项增加到1000项没有帮助)?另外,为什么Firefox是唯一显示我的Web服务器响应的浏览器?我想我的回答是无效的,对吗 Web服务器的代码:.net Tcplistener随机重置连接,.net,f#,network-programming,tcplistener,.net,F#,Network Programming,Tcplistener,我正在玩一个用F#编写的简单Web服务器。正如我所注意到的,如果我在Firefox中点击refresh,经过一些尝试后,我会看到一个错误页面,上面写着: 连接已重置 加载页面时已重置与服务器的连接 为什么这看起来是随机发生的(将待办事项增加到1000项没有帮助)?另外,为什么Firefox是唯一显示我的Web服务器响应的浏览器?我想我的回答是无效的,对吗 Web服务器的代码: module Program open System open System.Net.Sockets open Sys
module Program
open System
open System.Net.Sockets
open System.IO
type TcpListener with
member this.AsyncAcceptSocket =
Async.FromBeginEnd(this.BeginAcceptSocket, this.EndAcceptSocket)
type Main =
static member Init () =
let tcpListener = new TcpListener(80)
tcpListener.Start()
let rec loop =
async{
let! socket = tcpListener.AsyncAcceptSocket
Async.Start(loop)
let stream = new NetworkStream(socket)
let streamWriter = new StreamWriter(stream)
streamWriter.WriteLine("HTTP/1.0 200 OK");
streamWriter.WriteLine("Date: Fri, 15 Nov 2011 23:59:59 GMT");
streamWriter.WriteLine("Content-Type: text/html");
streamWriter.WriteLine("Content-Length: 13540");
streamWriter.WriteLine("")
streamWriter.WriteLine("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">");
streamWriter.WriteLine("<html>");
streamWriter.WriteLine("<body>");
streamWriter.WriteLine("<h1>This is the title</h1>");
streamWriter.WriteLine("</body>");
streamWriter.Write("</html>");
streamWriter.Flush()
stream.Close()
socket.Close()
}
Async.Start(loop)
Console.ReadLine()
Main.Init()
我想你想要
使用
成员:this.AsyncAcceptSocket()=
Async.FromBeginEnd(this.BeginAcceptSocket,this.EndAcceptSocket)
类型主=
静态成员Init()=
设tcpListener=新的tcpListener(80)
tcpListener.Start()
让rec循环()=
异步{
let!socket=tcpListener.AsyncAcceptSocket()
let stream=新网络流(套接字)
让streamWriter=新streamWriter(流)
streamWriter.WriteLine(“HTTP/1.0 200 OK”);
streamWriter.WriteLine(“日期:2011年11月15日星期五23:59:59 GMT”);
streamWriter.WriteLine(“内容类型:text/html”);
streamWriter.WriteLine(“内容长度:13540”);
streamWriter.WriteLine(“”)
streamWriter.WriteLine(“”);
streamWriter.WriteLine(“”);
streamWriter.WriteLine(“”);
streamWriter.WriteLine(“这是标题”);
streamWriter.WriteLine(“”);
streamWriter.Write(“”);
streamWriter.Flush()
stream.Close()
socket.Close()
return!loop()
}
Async.Start(循环())
Console.ReadLine()
Main.Init()
有几个变化:
循环
是一个函数,因此它需要在定义和调用它时接受单元()
(与异步接受套接字
相同)return结束!loop()
Async.Start
在AsyncAcceptSocket
返回之后这是一个有效的版本。我会使用TcpClient而不是socket,这样您就不必管理它的底层流
module Program
open System
open System.Net
open System.Net.Sockets
open System.IO
type TcpListener with
member this.AsyncAcceptTcpClient() =
Async.FromBeginEnd(this.BeginAcceptTcpClient, this.EndAcceptTcpClient)
type Main =
static member Init() =
let tcpListener = new TcpListener(IPAddress.Loopback, 80)
tcpListener.Start()
let writeContent() =
let stream = new MemoryStream()
let streamWriter = new StreamWriter(stream)
streamWriter.WriteLine("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">")
streamWriter.WriteLine("<html>")
streamWriter.WriteLine("<body>")
streamWriter.WriteLine("<h1>This is the title</h1>")
streamWriter.WriteLine("</body>")
streamWriter.Write("</html>")
streamWriter.Flush()
stream
let rec loop() =
async {
use! tcp = tcpListener.AsyncAcceptTcpClient()
let stream = tcp.GetStream()
use streamWriter = new StreamWriter(stream)
use content = writeContent()
streamWriter.WriteLine("HTTP/1.0 200 OK")
streamWriter.WriteLine("Date: Fri, 15 Nov 2011 23:59:59 GMT")
streamWriter.WriteLine("Content-Type: text/html")
streamWriter.WriteLine("Content-Length: {0}", content.Length)
streamWriter.WriteLine("")
streamWriter.Flush()
content.WriteTo stream
stream.Flush()
return! loop()
}
Async.Start(loop())
Console.ReadLine() |> ignore
Main.Init()
模块程序
开放系统
开放系统.Net
开放式System.Net.Sockets
开放系统
带有
成员this.asyncAcceptCpcClient()=
Async.FromBeginEnd(this.BeginAcceptTcpClient,this.EndAcceptCpcClient)
类型主=
静态成员Init()=
让tcpListener=新的tcpListener(IPAddress.Loopback,80)
tcpListener.Start()
let writeContent()=
let stream=new MemoryStream()
让streamWriter=新streamWriter(流)
streamWriter.WriteLine(“”)
streamWriter.WriteLine(“”)
streamWriter.WriteLine(“”)
streamWriter.WriteLine(“这是标题”)
streamWriter.WriteLine(“”)
streamWriter.Write(“”)
streamWriter.Flush()
流动
让rec循环()=
异步的{
使用!tcp=tcpListener.AsyncAcceptTcpClient()
let stream=tcp.GetStream()
使用streamWriter=新streamWriter(流)
使用content=writeContent()
streamWriter.WriteLine(“HTTP/1.0 200 OK”)
streamWriter.WriteLine(“日期:2011年11月15日星期五23:59:59 GMT”)
streamWriter.WriteLine(“内容类型:text/html”)
streamWriter.WriteLine(“内容长度:{0}”,Content.Length)
streamWriter.WriteLine(“”)
streamWriter.Flush()
content.WriteTo流
stream.Flush()
return!loop()
}
Async.Start(循环())
Console.ReadLine()|>忽略
Main.Init()
这并不是对您问题的真正回答,只是对循环和Async.Start
(我认为gradbot的版本应该可以工作,回答您的主要问题)
无论如何,与Daniel和gradbot相反,我认为您使用的Async.Start
并没有错,但可能只是混淆了(名称也很混乱)
- 实现它的方式是等待套接字,然后启动一个新的异步(准备立即接受新套接字),然后处理其余的工作。这意味着,您可以并行处理请求
- gradbot和Daniel实现它的方式是,他们接受一个套接字,向调用者发送回复,然后等待另一个套接字。这意味着处理是连续的
对
Async.Start(loop)
的调用看起来确实是错误的。有可能是因为您的内容长度不正确吗?对Async.Start
的调用看起来是错误的,但实际上我认为它在技术上没有什么问题(只是看起来有点混乱)。@Tomas:我是说第一个,不是第二个。调用Async.Start
2行进入loop
肯定不能按预期工作——这不会产生无限多的套接字吗?或者可能我遗漏了一些关于TcpListener
行为的细节…@ildjarn我认为这很好,因为它会在接受套接字(意味着连接了客户端)后生成工作流。然后,工作流的其余部分处理当前客户端,生成的工作流准备接受新客户端……虽然这些更改很好,但如果没有setti,它仍然无法工作
type TcpListener with
member this.AsyncAcceptSocket() =
Async.FromBeginEnd(this.BeginAcceptSocket, this.EndAcceptSocket)
type Main =
static member Init () =
let tcpListener = new TcpListener(80)
tcpListener.Start()
let rec loop() =
async{
let! socket = tcpListener.AsyncAcceptSocket()
let stream = new NetworkStream(socket)
let streamWriter = new StreamWriter(stream)
streamWriter.WriteLine("HTTP/1.0 200 OK");
streamWriter.WriteLine("Date: Fri, 15 Nov 2011 23:59:59 GMT");
streamWriter.WriteLine("Content-Type: text/html");
streamWriter.WriteLine("Content-Length: 13540");
streamWriter.WriteLine("")
streamWriter.WriteLine("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">");
streamWriter.WriteLine("<html>");
streamWriter.WriteLine("<body>");
streamWriter.WriteLine("<h1>This is the title</h1>");
streamWriter.WriteLine("</body>");
streamWriter.Write("</html>");
streamWriter.Flush()
stream.Close()
socket.Close()
return! loop()
}
Async.Start(loop())
Console.ReadLine()
Main.Init()
module Program
open System
open System.Net
open System.Net.Sockets
open System.IO
type TcpListener with
member this.AsyncAcceptTcpClient() =
Async.FromBeginEnd(this.BeginAcceptTcpClient, this.EndAcceptTcpClient)
type Main =
static member Init() =
let tcpListener = new TcpListener(IPAddress.Loopback, 80)
tcpListener.Start()
let writeContent() =
let stream = new MemoryStream()
let streamWriter = new StreamWriter(stream)
streamWriter.WriteLine("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">")
streamWriter.WriteLine("<html>")
streamWriter.WriteLine("<body>")
streamWriter.WriteLine("<h1>This is the title</h1>")
streamWriter.WriteLine("</body>")
streamWriter.Write("</html>")
streamWriter.Flush()
stream
let rec loop() =
async {
use! tcp = tcpListener.AsyncAcceptTcpClient()
let stream = tcp.GetStream()
use streamWriter = new StreamWriter(stream)
use content = writeContent()
streamWriter.WriteLine("HTTP/1.0 200 OK")
streamWriter.WriteLine("Date: Fri, 15 Nov 2011 23:59:59 GMT")
streamWriter.WriteLine("Content-Type: text/html")
streamWriter.WriteLine("Content-Length: {0}", content.Length)
streamWriter.WriteLine("")
streamWriter.Flush()
content.WriteTo stream
stream.Flush()
return! loop()
}
Async.Start(loop())
Console.ReadLine() |> ignore
Main.Init()
// Asynchronous function that handles communication with a single client
let handleClient (tcp:TcpClient) =
async {
try
let stream = tcp.GetStream()
use streamWriter = new StreamWriter(stream)
use content = writeContent()
streamWriter.WriteLine("HTTP/1.0 200 OK")
// Some stuff omitted
streamWriter.Flush()
content.WriteTo stream
stream.Flush()
finally
tcp.Dispose()
}
let mainLoop =
async {
while true do
// Wait for a client and start async workflow to process it
let! tcp = tcpListener.AsyncAcceptTcpClient()
Async.Start(handleClient tcp) }