简单的 unix 域套接字服务器

Simple unix domain sockets server

我不熟悉尝试使用 Unix 套接字进行编程,并且努力让简单的服务器正常工作。我希望它保持 运行 并打印它收到的消息,但它会打印第一条消息并退出。取决于 networkbytestring.

module Main where

import Network.Socket hiding (send, sendTo, recv, recvFrom)
import Network.Socket.ByteString
import qualified Data.ByteString.Char8 as C
import Control.Monad

main :: IO ()
main = withSocketsDo $ do
       sock <- socket AF_UNIX Stream 0 -- and try UDP?
       bind sock (SockAddrUnix "/tmp/test_sock.ipc")
       listen sock maxListenQueue -- TODO is maxListenQueue what we want?
       (conn, _) <- accept sock
       talk conn
       close conn
       close sock
       putStrLn "DONE"

    where
      talk :: Socket -> IO ()
      talk conn =
          do msg <- recv conn 1024
             unless (C.null msg) $ do
               C.putStrLn msg 
               talk conn

我正在使用 socat 进行测试,我也不知道如何使用它:

echo "FOOOOO" | socat - UNIX-CONNECT:/tmp/test_sock.ipc

任何关于 haskell 代码的指示,以及我可能对 unix 套接字的误解都会有所帮助。

EDIT 使用 Datagram 而不是 Stream 我能够或多或少地得到我想要的东西:

main::IO() main = withSocketsDo $ 做 sock <- socket AF_UNIX 数据报 0 -- 试试 UDP? 绑定 sock (SockAddrUnix "/tmp/test_sock.ipc") -- 对于数据报: 谈话袜 关闭袜子 putStrLn "DONE"

where
  talk :: Socket -> IO ()
  talk conn =
      do msg <- recv conn 1024
         unless (C.null msg) $ do
           C.putStrLn msg 
           talk conn

我可以通过以下方法成功测试:

echo "FOOOOO" | socat - UNIX-SENDTO:/tmp/test_sock.ipc

无论如何,我想我对数据报套接字很感兴趣,但如果有人想向我解释一些事情,我会保持开放状态。

您的代码只运行 "accept" 一次,因此它只能处理一个连接。如果要处理多个连接,则必须重复 "accept" 部分,而不仅仅是 "recv" 部分。

module Main where

import Network.Socket hiding (send, sendTo, recv, recvFrom)
import Network.Socket.ByteString
import qualified Data.ByteString.Char8 as C
import Control.Monad

main :: IO ()
main = withSocketsDo $ do
       sock <- socket AF_UNIX Stream 0 -- and try UDP?
       bind sock (SockAddrUnix "/tmp/test_sock.ipc")
       listen sock maxListenQueue -- TODO is maxListenQueue what we want?
       go sock
       close conn
       close sock
       putStrLn "DONE"

    where
      go sock = do
        (conn,_) <- accept sock
        talk conn
        go sock
      talk :: Socket -> IO ()
      talk conn =
          do msg <- recv conn 1024
             unless (C.null msg) $ do
               C.putStrLn msg 
               talk conn