在 Haskell 中构建和解析 SIP 消息(字符串)

发布于 2024-10-20 18:46:23 字数 1494 浏览 5 评论 0原文

我正在尝试通过编写 SIP 客户端来学习 Haskell。

我的问题是在下面的示例中,构建表示 SIP 请求的字符串的函数是什么样的,或者换句话说,而不是我正在对套接字句柄执行的 9 次写入,我将如何编写一个函数来构建字符串然后通过一次写入发送它?

上述问题的另一面是我如何解析从套接字返回的字符串以解析其中的所有信息。例如,每个 SIP 请求都有一个方法、URI、版本等。我是否应该使用单独的函数一次提取每个项目?

我在该任务中所做的尝试看起来与带有一个大“do”块的命令式代码完全相同,据我所知,这不是功能性的方式。

import Network
import System.Exit
import System.IO
import Text.Printf

server = "127.0.0.1"
port = 5060

main = do
  h <- connectTo server (PortNumber (fromInteger port))
  hSetBuffering h NoBuffering
  write h "OPTIONS sip:[email protected] SIP/2.0\r\n"
  write h "Via: SIP/2.0/TCP 192.168.0.153;branch-z9hg4bK4b1234\r\n"
  write h "To: sip:[email protected]\r\n"
  write h "From: <sip:[email protected]>;tag=1234\r\n"
  write h "CSeq: 1 OPTIONS\r\n"
  write h "Call-ID: abcdefgh\r\n"
  write h "Content-Length: 0\r\n"
  write h "\r\n"
  listen h

write :: Handle -> String -> IO ()
write h s = do
  hPrintf h "%s" s
  printf "> %s" s

listen :: Handle -> IO ()
listen h = forever $ do
    t <- hGetLine h
    let s = init t
    putStrLn s
  where
    forever a = do a; forever a

I'm attempting to learn Haskell by writing a SIP client.

The question I have is in the example below what would a function to build a string representing the SIP request look like, or in other words instead of the 9 writes I'm doing to the socket handle how would I write a function to build the string and then send it with one write?

The flip side of the above question is how would I parse the string I get back from the socket to parse all the information from it. For example each SIP request has a method, URI, version etc. should I extract each item with a separate function one at a time?

The attempts I've made at the task look exactly the same as imperative code with one big "do" block which from what I can tell is not the functional way.

import Network
import System.Exit
import System.IO
import Text.Printf

server = "127.0.0.1"
port = 5060

main = do
  h <- connectTo server (PortNumber (fromInteger port))
  hSetBuffering h NoBuffering
  write h "OPTIONS sip:[email protected] SIP/2.0\r\n"
  write h "Via: SIP/2.0/TCP 192.168.0.153;branch-z9hg4bK4b1234\r\n"
  write h "To: sip:[email protected]\r\n"
  write h "From: <sip:[email protected]>;tag=1234\r\n"
  write h "CSeq: 1 OPTIONS\r\n"
  write h "Call-ID: abcdefgh\r\n"
  write h "Content-Length: 0\r\n"
  write h "\r\n"
  listen h

write :: Handle -> String -> IO ()
write h s = do
  hPrintf h "%s" s
  printf "> %s" s

listen :: Handle -> IO ()
listen h = forever $ do
    t <- hGetLine h
    let s = init t
    putStrLn s
  where
    forever a = do a; forever a

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

假面具 2024-10-27 18:46:23

对于您的第一个问题:如何连接字符串并将它们写入一个操作中?这是一个例子:

--instead of
main = do
  h <- connectTo server (PortNumber (fromInteger port))
  hSetBuffering h NoBuffering
  write h "OPTIONS sip:[email protected] SIP/2.0\r\n"
  write h "Via: SIP/2.0/TCP 192.168.0.153;branch-z9hg4bK4b1234\r\n"
  write h "To: sip:[email protected]\r\n"
  write h "From: <sip:[email protected]>;tag=1234\r\n"
  write h "CSeq: 1 OPTIONS\r\n"
  write h "Call-ID: abcdefgh\r\n"
  write h "Content-Length: 0\r\n"
  write h "\r\n"
  listen h

--write
main = do
  h <- connectTo server (PortNumber (fromInteger port))
  hSetBuffering h NoBuffering
  write h $ "OPTIONS sip:[email protected] SIP/2.0\r\n"
    ++ "Via: SIP/2.0/TCP 192.168.0.153;branch-z9hg4bK4b1234\r\n"
    ++ "To: sip:[email protected]\r\n"
    ++ "From: <sip:[email protected]>;tag=1234\r\n"
    ++ "CSeq: 1 OPTIONS\r\n"
    ++ "Call-ID: abcdefgh\r\n"
    ++ "Content-Length: 0\r\n\r\n"
  listen h

关于解析:尝试 Parsec

PS:使用普通的String进行IO有点慢。尝试使用 ByteStringattoparsec 代替。

For your first question: How about concatting the strings and writing them in one single operation? Here's an example:

--instead of
main = do
  h <- connectTo server (PortNumber (fromInteger port))
  hSetBuffering h NoBuffering
  write h "OPTIONS sip:[email protected] SIP/2.0\r\n"
  write h "Via: SIP/2.0/TCP 192.168.0.153;branch-z9hg4bK4b1234\r\n"
  write h "To: sip:[email protected]\r\n"
  write h "From: <sip:[email protected]>;tag=1234\r\n"
  write h "CSeq: 1 OPTIONS\r\n"
  write h "Call-ID: abcdefgh\r\n"
  write h "Content-Length: 0\r\n"
  write h "\r\n"
  listen h

--write
main = do
  h <- connectTo server (PortNumber (fromInteger port))
  hSetBuffering h NoBuffering
  write h $ "OPTIONS sip:[email protected] SIP/2.0\r\n"
    ++ "Via: SIP/2.0/TCP 192.168.0.153;branch-z9hg4bK4b1234\r\n"
    ++ "To: sip:[email protected]\r\n"
    ++ "From: <sip:[email protected]>;tag=1234\r\n"
    ++ "CSeq: 1 OPTIONS\r\n"
    ++ "Call-ID: abcdefgh\r\n"
    ++ "Content-Length: 0\r\n\r\n"
  listen h

And about the parrsing: Try Parsec for this.

PS: Doing IO with usual Strings is a bit slow. Try ByteString and attoparsec instead.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文