在标准ML中使用TCP

时间:2015-06-03 00:32:18

标签: sockets tcp sml

我正在尝试在标准ML中编写一个最小的TCP服务器并获取一些我不理解的类型错误。到目前为止我得到的是

fun sendHello sock = 
    let val res = "HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello world!\r\n\r\n"
        val wds = map (fn c => Word8.fromInt (Char.ord c)) (String.explode res)
        val slc = ArraySlice.full (Array.fromList wds)
    in 
       Socket.sendArr (sock, slc)
       Socket.close sock
    end

fun acceptLoop serv =
    let val (s, _) = Socket.accept serv
    in print "Accepted a connection...\n";
       sendHello s;
       acceptLoop serv
    end

fun serve () =
    let val s = INetSock.TCP.socket()
    in Socket.Ctl.setREUSEADDR (s, true);
       Socket.bind(s, INetSock.any 8989);
       Socket.listen(s, 5);
       print "Entering accept loop...\n";
       acceptLoop s
    end

后两个函数运行正常(如果我注释掉sendHello行,他们会毫无怨言地进行类型检查,并设置一个服务器,每次客户端连接时都会打印Accepted a connection...

根据我对Socket struct的理解,sendArr应该采用套接字和Word8ArraySlice.slice的元组,我有理由相信这是我提供的。

SMLNJ

- ArraySlice.full (Array.fromList (map (fn c => Word8.fromInt (Char.ord c)) (String.explode "HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello world!\r\n\r\n"))) ;;
val it =
  SL
    {base=[|0wx48,0wx54,0wx54,0wx50,0wx2F,0wx31,0wx2E,0wx31,0wx20,0wx32,0wx30,
           0wx30,...|],start=0,stop=49} : Word8.word ArraySlice.slice
- 

我得到的错误是

- fun sendHello sock = 
    let val res = "HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello world!\r\n\r\n"
        val wds = map (fn c => Word8.fromInt (Char.ord c)) (String.explode res)
        val slc = ArraySlice.full (Array.fromList wds)
    in 
       Socket.sendArr (sock, slc)
       Socket.close sock
    end ;;
= = = = = = = stdIn:35.8-36.25 Error: operator and operand don't agree [tycon mismatch]
  operator domain: ('Z,Socket.active Socket.stream) Socket.sock * 
                   ?.Word8ArraySlice.slice
  operand:         ('Z,Socket.active Socket.stream) Socket.sock * 
                   Word8.word ArraySlice.slice
  in expression:
    Socket.sendArr (sock,slc)
- 

任何人都可以教我如何使其发挥作用吗?

1 个答案:

答案 0 :(得分:3)

事实证明,ArraySlice Word8Word8ArraySlice不同。为了从字符串中获取后者,您需要使用适当的数组调用packString。我决定使用Vector代替,这意味着我可以Word8VectorSlice.full (Byte.stringToBytes res)来获取我可以通过Socket.sendVec发送的内容。以下工作正常:

fun sendHello sock = 
    let val res = "HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello world!\r\n\r\n"
        val slc = Word8VectorSlice.full (Byte.stringToBytes res)
    in 
      Socket.sendVec (sock, slc);
      Socket.close sock
    end