이건 클라이언트 소스펼쳐두기..
import Prelude hiding (log)
import Network.Socket
import Control.Monad(liftM,forever)
import Control.Exception(finally)
import Control.Concurrent(forkIO)
-- withTcp 의 서버쪽 버전. 에러처리가 없으니 좀 허한데 테스트엔 문제
-- 없다.
serveTcp port f = do
s <- socket AF_INET Stream defaultProtocol
bindSocket s (SockAddrInet port iNADDR_ANY)
listen s maxListenQueue
forever $ do
(child,from) <- accept s
forkIO $ f child `finally` sClose child
-- 걍 화면에 출력만 하자.
log :: Socket -> IO ()
log sock = forever $ do
buf <- recv sock 1024
print (sock,buf)
main = withSocketsDo $ serveTcp 1818 log
-- 한가지 적어두자면, 원래 serveTcp 안에 forkIO 를 두지 않고
-- serveTcpMulti 란 함수를 만들어서 (forkIO . f) 를 serveTcp 로
-- 넘겨주는 식으로 만들었었다. 이런식으로 짜게 되면 serveTcp 가
-- 쓰레드방식에 대해서 독립적으로 돌아가니까.. 그런데 마지막에 child
-- 소켓을 닫아주는 처리가 좀 애매해지더라. forkIO 를 띄운 직후에
-- sClose 해버리면 자식쓰레드쪽에선 소켓이 닫혀버리니까..
--
-- 이걸 어떻게 이쁘게 해보려고 좀 고민해봤는데 좋은 방법이 안떠오르네.
-- 그런데 써둔걸 보니 나중에 읽어보면 뭔소린지 모르겠군..
으음... 이건 패킷이 너무 단순해서 별 의미는 없지만 위에 withTcp 나 serveTcp 는 자주 쓰일 함수들이라 적어둔다. 다음에는 현재 Socket 기반인것을 Handle 기반으로바꾸고.. 바이너리패킷을 쏘는걸 한번 만들어보고.. 그담엔 서로 주고받는걸 만들어보자...펼쳐두기..
import Network.Socket
import Control.Monad(liftM,forever)
import Control.Exception(finally)
import Control.Concurrent(threadDelay)
-- tcp 연결해서 f 에 넘기고 그 결과를 리턴. 흔한 with 류 함수
withTcp :: (String,PortNumber) -> (Socket->IO a) -> IO a
withTcp (ip,port) f = do
a <- liftM (SockAddrInet port) (inet_addr ip)
s <- socket AF_INET Stream defaultProtocol
connect s a
f s `finally` sClose s
-- 테스트서버는 위치가 고정이니 적당히 박았다.
withServer :: (Socket -> IO a) -> IO a
withServer = withTcp ("127.0.0.1",1818)
-- 패킷 쏘고 쉬고...
shootPackets :: Socket -> IO ()
shootPackets sock =
forever $ do
send sock "Hello"
threadDelay 1000000
main = withSocketsDo $ withServer shootPackets
댓글 없음:
댓글 쓰기