Я использую Network
и Gloss
для игрового сервера в Haskell. Он отлично работает, за исключением того, что клиент должен закрыть сервер для получения отправленных данных. Держу пари, это случай лени...
Минималистский сервер:
import Network
import System.IO
main = do
sock <- listenOn (PortNumber (fromIntegral 12345))
loop sock
loop sock = do
(hIn, _, _) <- accept sock
str <- hGetContents hIn
print str
loop sock
Минималистический клиент:
import Network
import System.IO
import Graphics.Gloss.Interface.IO.Game
main = playIO
(InWindow "Test Multi" (500, 500) (500, 500))
white
60
Nothing
draw
(\_ x -> return x)
advance
draw Nothing = return blank
draw (Just x) = return (Text (show x))
advance _ Nothing = do
hOut <- connectTo "000.000.0.0" (PortNumber (fromIntegral 12345))
hSetBuffering hOut NoBuffering
hPutStr hOut "Hello!"
return (Just hOut)
advance _ x = return x
Я запустил сервер, подождал 10 секунд, затем запустил клиент, подождал 15 секунд, посмотрел, что на сервере ничего не происходит, закрывает клиент, см. "Привет!" . неожиданно появляются на сервере.
Я бы хотел "Привет!" появляться во время работы клиента, в вызове advance
, иначе я не могу сделать многопользовательскую игру (всхлип)!
Однако, если я изменю код клиента на
main = loop Nothing
loop x = do
x' <- advance 0 x
getLine
the sever немедленно показывает "Привет!" . пока клиент ждет моего ввода.
Я попробовал, как было предложено в другом вопросе, использовать шаблоны ударов и hClose
:
-- ...
!str <- hGetContents hIn
hClose hIn
-- ...
который делает вывод немедленно, без закрытия клиента. Это здорово. Но я планирую использовать bytestrings, потому что данные, которые я отправляю на сервер, сериализуется, поэтому я import qualified Data.ByteString as B
и измените hGetContents
на B.hGetContents
, что заставляет проблему повторно появляться.
Проблема была действительно делом лени. hGetContents
лениво читает все содержимое Handle
, поэтому оно заканчивается только тогда, когда оно закрывается, когда клиент прерывает соединение. Вместо этого я использовал hGetLine
, который возвращает содержимое каждый раз, когда он встречает \n
, который я использую в качестве тега end-of-message
.