Haskell のゲーム サーバーにNetwork
andを使用しています。Gloss
サーバーが送信したデータを受信するためにクライアントを閉じる必要があることを除いて、正常に動作します。きっと怠惰の極み…
ミニマリスト サーバー:
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 秒待って、サーバーで何も起こらないことを確認し、クライアントを閉じます。「Hello!」が表示されます。サーバーに突然現れます。「こんにちは!」クライアントの実行中、advance
通話中に表示されない場合、マルチプレイヤー ゲームを作成できません (すすり泣く)!
ただし、クライアントのコードを次のように変更すると
main = loop Nothing
loop x = do
x' <- advance 0 x
getLine
サーバーはすぐに「Hello!」を表示します。クライアントが私の入力を待っている間。
別の質問で提案されているように、強打パターンとを使用しようとしましたhClose
:
-- ...
!str <- hGetContents hIn
hClose hIn
-- ...
これにより、クライアントを閉じることなく、出力がすぐに表示されます。それは素晴らしいことです。しかし、サーバーに送信するデータはシリアル化されるため、バイト文字列を使用する予定です。そのため、にimport qualified Data.ByteString as B
変更hGetContents
するとB.hGetContents
、問題が再発します。
問題は確かに怠惰の場合でした。hGetContents
のすべてのコンテンツを遅延して読み取るHandle
ため、クライアントが接続を中止したときに、それが閉じられたときにのみ終了します。代わりに、タグとして使用する にhGetLine
遭遇するたびにコンテンツを返すを使用しました。\n
end-of-message