【发布时间】:2012-02-27 01:36:27
【问题描述】:
更新:问题现在包含最终编辑的答案!
我现在使用以下(最终答案):
module Main where
import Control.Concurrent (forkIO)
import Control.Monad (when,forever,void)
import Network (PortID(PortNumber),listenOn)
import Network.Socket hiding (listen,recv,send)
import Network.Socket.ByteString (recv,sendAll)
import qualified Data.ByteString as B
import System
type Host = String
type Port = PortNumber
main :: IO ()
main = do
[lp,h,p] <- getArgs
start (port lp) h (port p)
where
port = fromInteger . read
start :: Port -> Host -> Port -> IO ()
start lp rh rp = withSocketsDo $ do
proxy <- listenOn $ PortNumber lp
forever $ do
(client,_) <- accept proxy
void . forkIO $ (client >-<) =<< rh .@. rp
(.@.) :: Host -> Port -> IO Socket
host .@. port = do
addr:_ <- getAddrInfo Nothing (Just host) (Just $ show port)
server <- socket (addrFamily addr) Stream defaultProtocol
connect server (addrAddress addr)
return server
(>-<) :: Socket -> Socket -> IO ()
x >-< y = do x >- y; y >- x
(>-) :: Socket -> Socket -> IO ()
s >- r = void . forkIO . handle $ forever stream
where
stream = recv s (64 * 1024) >>= ifNot0 >>= sendAll r
ifNot0 = \c -> do when (B.null c) $ handle (error "0"); return c
handle = flip catch $ \e -> print e >> sClose s >> sClose r
可以这样运行:
proxy 2000 localhost 3389
使用mRemote,如果我连接到localhost:2000,我会看到本地机器的登录屏幕! :)
*如果我找到进一步改进(>-) 的方法,我会更新这个答案!
【问题讨论】:
-
你想用他的代码解决什么具体问题?
-
@MikePennington ,我只是在问题的最后描述了我要解决的问题。
-
@Cetin Sert:所以你的问题是如何让它更快?
-
@NiklasB。更快并且使用尽可能少的内存,无需在
(>-)内创建content -
我没有关于如何加快速度的好建议,但对风格有两点说明。
ignore函数已在Control.Monad中可用,名称为void。//的名称也不太具描述性,我最好使用普通的sClose from >> sClose to。
标签: sockets networking haskell proxy network-programming