newLISP TCP通信的一些技巧

如何发送字节数组

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.




你可能感兴趣的:(newLISP TCP通信的一些技巧)