F# 尝试将 HTTP 响应写入 TCP 流
F# Trying to write HTTP response to TCP stream
我正在尝试用 F# 制作一个简单的 HTTP 服务器。但不幸的是,我停留在响应阶段,我正在尝试创建一个简单的 404 响应,但我的浏览器无法获取它,它只会加载和加载页面,永远不会去任何地方。我不知道我的代码哪里有问题。
let responseString = "HTTP/1.1 404 NOT FOUND";
let buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
let processRequest (client: TcpClient) =
async { do printfn "Incoming HTTP request..."
use stream = client.GetStream()
use sr = new StreamReader(stream)
let! content = sr.ReadToEndAsync() |> Async.AwaitTask
do
printfn "Stream contains:\n%s" content
stream.Write(buffer, 0, buffer.Length)
stream.Flush() }
let ip = IPAddress.Parse("127.0.0.1")
let listener = TcpListener(ip, 8080)
let startServer =
async { do listener.Start()
do printfn "Starting server..."
while true do
let! context = listener.AcceptTcpClientAsync() |> Async.AwaitTask
do! processRequest context }
Async.Start startServer
问题是,TCP 流不知道客户端何时发送了所有数据(除非您关闭浏览器),因此 StreamReader 永远被阻塞。
如果你想自己实现 HTTP,你需要(对于初学者)逐行读取并检查是否允许客户端发送更多数据。
正如@CaringDev 指出的那样,ReadToEnd 不会终止。也就是说,对于一个简单的 HTTP 服务器,您只需要阅读请求的第一行。这是您的代码的更新版本,它只读取第一行并以 200 OK 响应:
open System.Net
let processRequest (client: Sockets.TcpClient) = async {
printfn "Incoming HTTP request..."
use stream = client.GetStream()
use sr = new System.IO.StreamReader(stream)
let line = sr.ReadLine()
printfn "Request: %s" line
let sw = new System.IO.StreamWriter(stream)
sw.WriteLine("HTTP/1.1 200 OK\r\n\r\nHello World")
sw.Flush()
}
let ip = IPAddress.Parse("127.0.0.1")
let listener = Sockets.TcpListener(ip, 8080)
let startServer = async {
do listener.Start()
do printfn "Starting server..."
while true do
let! context = listener.AcceptTcpClientAsync() |> Async.AwaitTask
processRequest context |> Async.Start
}
Async.Start startServer
我也很想将 do! processRequest context
更改为 processRequest context |> Async.Start
以便您可以同时处理多个请求。
我正在尝试用 F# 制作一个简单的 HTTP 服务器。但不幸的是,我停留在响应阶段,我正在尝试创建一个简单的 404 响应,但我的浏览器无法获取它,它只会加载和加载页面,永远不会去任何地方。我不知道我的代码哪里有问题。
let responseString = "HTTP/1.1 404 NOT FOUND";
let buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
let processRequest (client: TcpClient) =
async { do printfn "Incoming HTTP request..."
use stream = client.GetStream()
use sr = new StreamReader(stream)
let! content = sr.ReadToEndAsync() |> Async.AwaitTask
do
printfn "Stream contains:\n%s" content
stream.Write(buffer, 0, buffer.Length)
stream.Flush() }
let ip = IPAddress.Parse("127.0.0.1")
let listener = TcpListener(ip, 8080)
let startServer =
async { do listener.Start()
do printfn "Starting server..."
while true do
let! context = listener.AcceptTcpClientAsync() |> Async.AwaitTask
do! processRequest context }
Async.Start startServer
问题是,TCP 流不知道客户端何时发送了所有数据(除非您关闭浏览器),因此 StreamReader 永远被阻塞。 如果你想自己实现 HTTP,你需要(对于初学者)逐行读取并检查是否允许客户端发送更多数据。
正如@CaringDev 指出的那样,ReadToEnd 不会终止。也就是说,对于一个简单的 HTTP 服务器,您只需要阅读请求的第一行。这是您的代码的更新版本,它只读取第一行并以 200 OK 响应:
open System.Net
let processRequest (client: Sockets.TcpClient) = async {
printfn "Incoming HTTP request..."
use stream = client.GetStream()
use sr = new System.IO.StreamReader(stream)
let line = sr.ReadLine()
printfn "Request: %s" line
let sw = new System.IO.StreamWriter(stream)
sw.WriteLine("HTTP/1.1 200 OK\r\n\r\nHello World")
sw.Flush()
}
let ip = IPAddress.Parse("127.0.0.1")
let listener = Sockets.TcpListener(ip, 8080)
let startServer = async {
do listener.Start()
do printfn "Starting server..."
while true do
let! context = listener.AcceptTcpClientAsync() |> Async.AwaitTask
processRequest context |> Async.Start
}
Async.Start startServer
我也很想将 do! processRequest context
更改为 processRequest context |> Async.Start
以便您可以同时处理多个请求。