2012-03-05 35 views
1

以下の機能は、デュアタイムが到来して復帰するまで受信して待ちます。ループが終了していません

今、受信して応答すると動作します。 ackが受信されず、duetimeになるまで正常に動作します。

デュアタイムに達すると、フリーズします。私の自己構築ループを正しく終了していないようです。私はif-then-elseでも試しましたが、同じ結果です。私はwhileMを使いたくない。

ループを正しく終了するにはどうすればよいですか?

import Network.Socket hiding (send, sendTo, recv, recvFrom) 
import Network.Socket.ByteString 


waitAck s duetime' = do 
     print ("in") 
     (a, _) <- recvFrom s 4711 
     now' <- getPOSIXTime 
     unless (B.unpack a == "ack") (when (now' < duetime') (waitAck s duetime')) 
     print (B.unpack a) 
     return() 
+0

を - あなたはタイムアウト後の入力を待って停止するように何の指示を得なかっました渡します。あなたは['select'](http://linux.die.net/man/2/select)に相当するhaskellを見つける必要があります。 – rampion

+0

'recvFrom'は、タイムアウトのためにIMHOがブロックしていない –

答えて

4

正しい解決策は、2つのスレッド(ackを待機するスレッドと1つのスレッドを競合する)です。レースを失うものを殺す。 baseは、まさにこの目的のためにSystem.Timeout.timeoutを提供しているようです:

import Control.Concurrency.MVar 

withTimeout :: Int -> IO a -> IO (Maybe a) 
withTimeout n io = do 
    mvar <- newEmptyMVar 
    timeout <- forkIO (threadDelay n >> putMVar mvar Nothing) 
    action <- forkIO (io >>= putMVar mvar . Just) 
    result <- takeMVar mvar 
    killThread timeout 
    killThread action 
    return result 

waitAck s timeout = withTimeout timeout go where 
    go = do 
     (a, _) <- recvFrom s 4711 
     if B.unpack a == "ack" then print (B.unpack a) else go 

編集:おそらく、この(未テスト)コードは、あなたの方法についてのヒントを与えるだろう。その実装はこの実装よりも正しい可能性が高くなります。

+0

ありがとうございます。これを調べます。 Conc MVarは、より大きなスケールで使用されている場合、これがかなり遅いと予想しています。私は、最小限の量のコードと一緒になる非常に速いものを工作しようとします。私はMVarのものも試してみます。 –

+0

タイムアウトに達すると、 'just a

+0

@JFritsch:タイムアウトした場合、結果は 'Nothing'なので、マッチ 'ちょうど'。 – hammar

1

これは反復ループではありません。あなたは再帰呼び出しの後に何か条件を置かないので、条件が最終的に失敗すると、すべてのものが巻き戻され、再帰呼び出しごとに1回印刷されます。私はそれが凍っているように見えるのではないかと思う。

このような何か試してください:あなたはすでにいくつかのデータを受け取ってきた後ので、あなたは `duetime'`をチェックするだけの時間がある

waitAck s duetime' = do 
    print ("in") 
    (a, _) <- recvFrom s 4711 
    now' <- getPOSIXTime 
    if B.unpack a == "ack" || now' >= duetime' 
     then print (B.unpack a) 
     else waitAck s duetime' 
+0

がフリーズします。まったく同じ結果です。私はこのコンパイルが期待されたことはなかった。 cond2は両方とも同じ型でなければなりません。 –

+0

@JFritsch:その場合、 'recvFrom'がブロックされているようです。また、 '' B.unpack a == "ack" 'と' now '> duetime''はどちらも 'Bool'型です。 – hammar

関連する問題