如何从TCP读取并写入标准输出?

10

我无法运行一个简单的scalaz-stream示例,从TCP读取并写入标准输出。

val src = tcp.reads(1024)
val addr = new InetSocketAddress(12345)
val p = tcp.server(addr, concurrentRequests = 1) {
  src ++ tcp.lift(io.stdOutLines)
}
p.run.run
它只是静静地待在那里,什么也不打印。 我也尝试过使用to进行各种排列组合,总是需要使用tcp.lift来获取Process[Connection, A]
tcp.server(addr, concurrentRequests = 1)(src) map (_ to tcp.lift(io.stdOutLines))

甚至无法编译。

我需要将源流和打印流合并吗?我在原始拉取请求中找到的一个示例,用tcp替换nio,似乎是这样指示的,但wye现在不再出现在Process上,所以遗憾地产生了混淆。


编辑事实证明,除了保罗解释的类型问题之外,您还需要“手动”运行内部进程,例如通过执行p.map(_.run.run).run.run。我不认为这是惯用的做法,但它确实有效。

1个回答

5
您需要将src通过sink传递才能实际写入任何内容。我认为这应该可以做到:
import scalaz.stream.{io,tcp,text}
import scalaz.stream.tcp.syntax._

val p = tcp.server(addr, concurrentRequests = 1) { 
  tcp.reads(1024).pipe(text.utf8Decode) through tcp.lift(io.stdOutLines) 
}
p.run.run

表达式src ++ tcp.lift(io.stdOutLines)应该是类型错误。 tcp.reads(1024)的类型是Process[Connection,ByteVector],而tcp.lift(io.stdOutLines)的类型是Process[Connection, String => Task[Unit]]。将这两个进程附加在一起没有意义,它可以通过Process[+F[_],+O]的协变性而编译通过。当您附加两个具有不相关输出类型的进程时,Scala会“有用地”推断Any
scalaz-stream的未来版本可能会对++和其他利用协变性的函数添加约束,以确保计算的最小上界不是无用的东西,例如AnySerializable。这将有助于防止此类错误。同时,请确保您了解所有正在使用的函数的类型、功能及其如何结合使用。

1
使用sbt wart-remover可能会捕捉到任何推断。 - Channing Walton
你的意思是在没有使用 tcp.lift 的情况下通过 io.stdOutLines 吗?但似乎仍然无法从流中获取任何内容。 - Joe Kearney
好的 - 去掉 tcp.lift 后,这个程序可以工作,但请注意你必须使用 p.map(_.run.run).run.run 来运行内部进程。 - Joe Kearney

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接