我只是在学习FP,所以也许我做错了。
使用cats,cats-effects,fs2,fs2-io。
以下代码将port作为参数,然后在给定端口上创建连接到127.0.0.1的服务器套接字和客户端套接字。
我需要此函数返回的是分配的服务器套接字端口。
Int => F[Int]
?我正在使用cats-effects IOApp运行该程序。
我的代码:
trait TCP[F[_]] {
def createTunnel(localPort: Int): F[TCP.CreatedTunnel]
}
object TCP {
implicit def apply[F[_]](implicit ev: TCP[F]): TCP[F] = ev
final case class CreatedTunnel(remotePort: Int) extends AnyVal
def impl[F[_]: Applicative : ContextShift : ConcurrentEffect](socketGroup: SocketGroup): TCP[F] = new TCP[F] {
override def createTunnel(localPort: Int): F[CreatedTunnel] = {
val localBindAddress = Deferred[F, InetSocketAddress]
val stream = Stream
.eval(socketGroup.serverWithLocalAddress[F](new InetSocketAddress(InetAddress.getByName("0.0.0.0"), 0)))
.flatMap {
case Left(localAddress) =>
Stream.eval_(localBindAddress.flatMap(_.complete(localAddress)))
case Right(serverSocket) =>
Stream.resource(serverSocket.map { socket =>
Stream
.eval(socketGroup.client[F](new InetSocketAddress("127.0.0.1", localPort)))
.map { clientSocket =>
clientSocket.reads(1024).through(socket.writes())
socket.reads(1024).through(clientSocket.writes())
}
})
}
// -------------------------------------------
// (!!!) I need to return this,
// but i need to run stream above first
// -------------------------------------------
localBindAddress.map(_.get.map(addr => TCP.CreatedTunnel(addr.getPort)))
}
}
}