Während Tauchen in Haskell Network
Bibliothek, mache ich einen sehr einfachen HTTP-Server basierend auf Informationen aus this link.Basic `listenOn` HTTP-Server" Recv Fehler: Verbindung zurückgesetzt durch Peer "
import Control.Concurrent
import Control.Monad
import Network
import System.IO
main = withSocketsDo $ listenOn (PortNumber 8080) >>= loop
loop :: Socket -> IO()
loop sock = do
(h,_,_) <- accept sock
forkIO $ handleRequest h
loop sock
handleRequest :: Handle -> IO()
handleRequest h = do
hPutStr h $ httpRequest "Pong!\n"
hFlush h
hClose h
httpRequest :: String -> String
httpRequest body = "HTTP/1.0 200 OK\r\n"
++ "Content-Length: " ++ (show.length) body ++ "\r\n"
++ "\r\n" ++ body ++ "\r\n"
Doch obwohl ich es schaffe eine Antwort zu erhalten, scheint die Griffe unerwartet bald geschlossen werden, wie Locke sagt mir (manchmal?):
$ curl localhost:8080
Pong!
curl: (56) Recv failure: Connection reset by peer
NB: Manchmal weiß ich nicht erhalten Sie sogar die Nachricht (Pong!
) oder nur einen Teil davon. Manchmal funktioniert es ... aber wenn ich 100 curl
s in einer Reihe laufen lasse, bekomme ich schließlich einige Verbindung zurücksetzt.
Warum wird die Verbindung zurückgesetzt? Ich habe mit und ohne forkIO
ohne Erfolg versucht. Habe ich etwas Wesentliches über IO-Streams in Haskell verpasst? Vielen Dank!
OS: aktuelle Ubuntu; GHC: 7.8.4
--- Edit: ---
jozefg identifiziert, dass das Problem kam die Anfrage des Inhalts von der Entwässerung! Allerdings würde ich gerne diesen Inhalt senden zurück an den Client und es hängt, während mit dem folgenden Code:
handleRequest :: Handle -> IO()
handleRequest h = do
contents <- getHandleContents h
hPutStr h $ httpRequest contents
hFlush h
hClose h
getHandleContents :: Handle -> IO String
getHandleContents h = do
iseof <- hIsEOF h
if iseof
then return []
else do
newLine <- hGetLine h
nextLines <- getHandleContents h
return $ newLine ++ '\n' : nextLines
Außerdem hatte ich keinen Erfolg, den gesamten Inhalt mit hGetContents
abzulassen. Irgendeine Idee warum?
Um meine zusätzliche Frage in der Bearbeitung zu beantworten: Ich kann nicht versuchen, bis EOF zu lesen, weil es die Rolle des Servers ist, die Verbindung zu schließen (so würden wir nur auf nichts warten). Wenn der Client stattdessen den Header "Content-Length" angibt, würden wir die Anzahl der angegebenen Bytes lesen, um den Rumpf zu erhalten. Dies erklärt auch, warum 'hGetContents' das Programm aufhängt. – blint
Sie schließen den Griff, bevor alles geschrieben ist. Wenn Sie den Griff schließen, schließen Sie auch die Verbindung. Durch das Entfernen von "hClose h" funktioniert es zu 100% auf meinem Computer. Die Lösung * in der Praxis * besteht darin, eine HTTP-Server-Bibliothek auf höherer Ebene zu verwenden und sich um diese Dinge zu kümmern. – user2407038