我已将套接字配置为读取部分数据,如下所示:
@socket = new Windows.Networking.Sockets.StreamSocket()
hostName = new Windows.Networking.HostName(@ip)
@ensureConnection = @socket.connectAsync(hostName, @port.toString())
.then () =>
@writer = new DataWriter(@socket.outputStream)
@reader = new DataReader(@socket.inputStream)
@reader.inputStreamOptions = InputStreamOptions.partial
然后我从套接字读取的函数如下所示:
readLineAsync = (reader, buffer = "") ->
while reader.unconsumedBufferLength
byte = reader.readByte()
if byte is 0
return WinJS.Promise.as(buffer)
buffer += String.fromCharCode(byte)
reader.loadAsync(1024).then (readBytes) ->
if readBytes is 0
WinJS.Promise.as(buffer)
else
while reader.unconsumedBufferLength
byte = reader.readByte()
if byte is 0
return WinJS.Promise.as(buffer)
buffer += String.fromCharCode(byte)
readLineAsync(reader, buffer)
此功能有2个问题:
对于非常大的响应,堆栈会使用递归的readLineAsync调用进行构建。我怎么能防止这种情况?我是否应该使用WinJS Scheduler API或类似工具将下一次调用排队到readLineAsync
?
有时,当套接字上没有数据时,reader.loadAsync无法完成。有时确实如此,readByte
则为0。那是为什么?
为什么我在该函数的2个位置上循环读取器的uncunsumedBufferLength?我最初在loadAsync延续处理程序中有这个代码。但由于响应可以包含终止\0
char,因此我需要在函数输入时检查读取器缓冲区中的未读数据。
这是用于向套接字发送/接收的伪循环:
readResponseAsync = (reader) ->
return readLineAsync(@reader).then (line) ->
result = parseLine(line)
if result.unknown then return readResponseAsync(reader)
return result
@ensureConnection.then () =>
sendCommand(...)
readResponseAsync(@reader).then (response) ->
# handle response
来自MS的所有WinRT示例都处理套接字上的已知数据量,因此它们并不适合我的场景。