如何发送字节数组
net-send仅仅接受string作为参数,也就是说只能发送字符串。
后来才发现,原来这只是这个API的接口,通过字符串仍然能够发送二进制数据,比如:
> (net-send socket "\019\000")
2
只需要前面加上\转义符号即可。
如何发送16位整数,并按照big-endian顺序发送
答案是pack。看下面的例子:
> (set 'socket (net-connect "localhost" 8889))
5
> (set 'size (pack ">u" 19))
"\000\019"
> (net-send socket size)
2
">u" 指定了这是一个unsigned short,而且是big-endian字节顺序,19将被转换成"\000\019"
注意,这里的低地址是从左开始的,也就是整数19的高字节0位于最低地址上,因此的确是big-endian.
如何在接收到的二进制数据中获取指定位置的字节
答案是address和+,下面有两个辅助函数:
(define (pick-byte buffer offset)
(get-char (+ (address buffer) offset)))
(define (pick-char buffer offset)
(char (pick-byte buffer offset)))
看看怎么使用?
(unless (net-receive socket message 13) (quit-for-error))
(println (pick-byte message 0))
(println (pick-char message 1))
先从TCP连接中读取13个字节,存放在message symbol中。然后用address获取message在内存中的其实地址,再用+获取第n个字节的内存地址,这时得到的字节,可以用char将其转换成ASCII字符。
如何在接收到的二进制数据中获取连续的字节
下面有两个函数,一个获取连续字节,一个获取连续字符串,前者返回list, 后者返回字符串
;; extract the bytes from buffer in [start, end) and return it as a list
(define (pick-bytes buffer start end)
(let (l '())
(dotimes (x (- end start))
(push (pick-byte buffer (+ start x)) l -1))))
;; extract the string from buffer in [start, end) and return it as a string
(define (pick-string buffer start end)
(let (l "")
(dotimes (x (- end start))
(push (pick-char buffer (+ start x)) l -1))
))
我的程序中,取四个连续字符,这是一个16进制的字面常量,下面用int将其转换成整数
(unless (net-receive socket message 13) (quit-for-error))
(println (int (append "0x" (pick-string message 1 5))))
解析出来的是"000D", 加上0x后变成"0x000D" 用int函数转换后变成13.