- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在编写一个服务器,其中一个要求是它需要能够向客户端推送数据,而无需客户端直接请求数据。我正在使用管道,但感觉这超出了管道的能力。我遇到的问题是,似乎没有办法判断套接字是否有可用数据,等待将阻止执行,直到有可用数据。假设我有以下功能
getPacket :: Conduit ByteString IO ClientPacket --take a bytestring and yield a ClientPacket i.e. the ByteString deserialized into a sensible form
processPacket :: Conduit ClientPacket IO ServerPacket --take a ClientPacket and yield a ServerPacket i.e. a response to the client's request
putPacket :: Conduit ServerPacket IO ByteString --serialize the ServerPacket
然后我将管道与来自 Conduit.Network 库的源和接收器连接在一起
appSource appData $$ getPacket =$= processPacket =$= putPacket $= appSink appData
现在,我从管道外部引入一个数据源,我想将该数据合并到管道中。例如,如果这是一个聊天服务器,则外部数据将是其他客户端发送的消息。问题是无论我尝试在何处引入这些外部数据,它都会被等待调用阻塞。本质上,我最终会得到如下所示的代码。
yield processOutsideData --deal with the outside data
data <- await --await data from upstream
处理更多外部数据的唯一方法是上游组件产生某些东西,但上游只有在从客户端获取数据时才会产生,这正是我试图避免的。我试过使用多线程和 TChan 来解决这个问题,但似乎 appSource 和 appSink 必须在同一个线程中使用,否则我会从 recv 中得到无效的文件描述符异常(这是有道理的)。
但是,如果套接字源和接收器在同一个线程中运行,我将再次遇到等待阻塞的问题,并且我无法检查套接字中是否有数据可用。在这一点上,我似乎遇到了管道问题。
但我真的很喜欢使用导管,并且愿意继续使用它们。所以我的问题是:有没有办法通过管道实现我想要实现的目标?
最佳答案
Michael Snoyman 的 conduit network examples use concurrency . telnet 客户端示例运行一个线程用于发送输入,另一个线程用于显示接收到的内容。我已经调整它来发送和接收整行
{-# LANGUAGE OverloadedStrings #-}
import Conduit
import Control.Concurrent.Async (concurrently)
import Control.Monad (liftM, void)
import Data.ByteString (ByteString)
import Data.ByteString.Char8 (unpack)
import Data.Conduit.Network
import Data.String (IsString, fromString)
import Network (withSocketsDo)
getLines :: (IsString a, MonadIO m) => Producer m a
getLines = repeatMC . liftM fromString $ liftIO getLine
putLines :: (MonadIO m) => Consumer ByteString m ()
putLines = mapM_C $ liftIO . putStrLn . unpack
main :: IO ()
main = withSocketsDo $
runTCPClient (clientSettings 4000 "localhost") $ \server ->
void $ concurrently
(getLines $$ appSink server)
(appSource server $$ putLines)
我们可以在服务器上做同样的事情。创建一个STM channel ,将接收到的数据写入 channel ,并将 channel 中的数据发送给客户端。这使用 stm-conduit包对 STM channel 的简单包装,sourceTBMChan
和 sinkTBMChan
。
{-# LANGUAGE OverloadedStrings #-}
import Conduit
import Control.Concurrent.Async (concurrently)
import Control.Concurrent.STM.TBMChan (newTBMChan)
import Control.Monad (void)
import Control.Monad.STM (atomically)
import Data.Conduit.Network
import Data.Conduit.TMChan (sourceTBMChan, sinkTBMChan)
import Network (withSocketsDo)
main :: IO ()
main = withSocketsDo $ do
channel <- atomically $ newTBMChan 10
runTCPServer (serverSettings 4000 "*") $ \server ->
void $ concurrently
(appSource server $$ sinkTBMChan channel False)
(sourceTBMChan channel $$ appSink server)
如果我们在只连接一个客户端的情况下运行服务器,它会回显客户端发送的内容。
----------
| a | (sent)
| a | (received)
| b | (sent)
| b | (received)
| c | (sent)
| c | (received)
----------
如果我们在连接多个客户端的情况下运行服务器,则消息会在客户端之间分发,一个客户端获取每条消息。
---------- ----------
| 1 | (sent) | 1 | (received)
| 2 | (sent) | 3 | (received)
| 2 | (received) | |
| 3 | (sent) | |
| | | |
| | | |
---------- ----------
此示例不处理客户端关闭连接时要执行的操作。
关于multithreading - 有没有办法让管道从多个来源获取数据而不阻塞其中任何一个?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31932931/
我正在用 robocopy 编写一个 powershell 脚本来从列表中复制“完整的”unc/文件名路径。我遇到的问题是 robocopy 似乎在我的源路径末尾添加了一个 \。 我有一个 C:\te
我发现守护程序通过这些代码创建了一个容器 // NewBaseContainer creates a new container with its // basic configuration. fu
是否有所有潜在 map 源的列表?在示例页面上,可以浏览四种类型的 map 。外面还有什么? http://tombatossals.github.io/angular-leaflet-directi
是否有所有潜在 map 源的列表?在示例页面上,可以浏览四种类型的 map 。外面还有什么? http://tombatossals.github.io/angular-leaflet-directi
我们的网站比较多,第一次使用ElasticSearch不知道应该怎么配置ES: 我们想使用 ES 作为这些网站的唯一搜索引擎,我们是否应该为每个网站设置单独的 ES 实例? (我想这可能比一个 ES
我需要一些关于我对 UNI 项目的想法的建议。 我想知道是否可以将一个音频文件从不同的音频源分成不同的“流”。例如,将音频文件拆分为:引擎噪音、火车噪音、人声、并非始终存在的不同声音等。 我不一定需要
我想设置“公共(public)彩票”,每个人都可以看到选择是随机和公平的。如果我只需要一点,我会使用例如当天收盘道琼斯指数的 LSB。问题是,我需要 32 位。我需要一个来源: 每日可用 全世界都可以
来自 pickle 的 python 文档: Warning The pickle module is not secure. Only unpickle data you trust. 什么是 pi
我试图安排一个 liquidsoap 流媒体源在未来的特定日期和时间播放。我相信这可以使用 Liquidsoap switch 命令来完成,但我无法理解此处描述的文档:http://liquidsoa
对于Shiny应用程序,我希望能够播放在 session 本身期间生成的音频文件。 如果它是我要上传的音频文件,我将使用 tags$audio(src = "www/name.wav", ty
我想更改我的 OpenGL 来源。图片会说明: 现在是这样的: 这就是我想要的: 当前代码 gl.glViewport(0, 0, width, height); gl.glMatrixMode(GL
我正在尝试让 Stripe 运行起来,我几乎已经完成了,但有一件令人困惑的事情。 source: 'tok_visa' 部分。看起来它可以是“tok_mastercard”、“bank_account
我已经下载了 primefaces 源代码,看看是否可以从中学习。该 jar 包含一堆使用编写器来处理渲染等的 java 类。我期待找到一些 .xhtml 文件 ... and etc etc
如果我查看页面源代码,我会看到 styling += 'ul#topnav a.tabHeader5'; styling += '{'
我正在尝试根据显示器的大小更改背景图像。它不在服务器上运行。您可以在 https://github.com/Umpalompa/Umpalompa.github.io 找到我的所有代码. 我尝试同时使
从here的最底部开始.有一个 URL 生成器,我可以使用引荐来源网址在 Google Play 上生成指向我的应用程序的链接。我如何从谷歌分析中提取该 Activity 来源?我一直在谷歌上搜索,但
我用 Google Weather API 制作了一个插件,目前我正在从 Google 的 API 中提取图像。对于晴天,我正在拉 http://www.google.com//ig/images/w
是否可以通过环境变量为 @CrossOrigin 注释指定来源?我想这样做,以便我可以将相同的代码库用于 uat/staging/production。我希望我的 uat/staging 环境可以通过
我需要等待我的 JavaScript 中的文档准备就绪,才能在正文底部插入一个 div。 我想: 使此 JavaScript 文件尽可能小(如果可能,将其编译到 < 1kb) 在闭包中内联提供文档就绪
我正在开发电子邮件服务并想连接到谷歌帐户,是否可以将我的本地主机用作授权的 JavaScript 来源? 最佳答案 第 1 步:启用 Google+ API http://localhost:4567
我是一名优秀的程序员,十分优秀!