I need to get the status of a list of devices from my home automation server. The devices I want to query for are in an array.
I'm triyng to loop thru that array, and for each devices, I'm doing a send to the server. The problem I have is that the server receive only one string containing my 3 commands.
The loop send this 3 commands:
gs,6297\r\n
gs,5867\r\n
gs,9737\r\n
I read in a lot of place that I only need to append a carriage return line feed to solve my problem but it’s not working.
I’ve used Wireshark to analyse what was happening. The 3 commands are sent as one big string:
gs,6297..gs,5867..gs,9737..
Where .. is 0d 0a.
I’ve implement my NSStream like seen in many place using the run-loop way:
outputStream!.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
This is my Send function:
func send(message:String){
if (self.outputStream!.hasSpaceAvailable){
let data:NSData = message.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
let bytesWritten = self.outputStream!.write(UnsafePointer(data.bytes), maxLength: data.length)
println("> \(message) | Length: \(data.length)")
} else {
println("# stream busy")
}
}
And my querying loop:
func GetDeviceStatus(array: [sDevice]){
for (index, value) in enumerate(array) {
while (true) {
if (self.outputStream!.hasSpaceAvailable){
self.send("gs,\(value.DevRef)\r\n")
sleep(1)
break
}
}
}
}
Perhaps, the loop is to fast. If I uncomment the sleep(1), the server receive 3 commands and the Read() function receive 3 distincts responses. All is working. But adding that sleep function is blocking and slow…
Anybody can help? I’ve spent to much time with this issue.
Your problem is that you think TCP preserves message boundaries, but it doesn't. A TCP connection is a stream of bytes, not a stream of messages. Your server can't assume that it will read each command as a separate "message". Instead, it needs to look through the bytes it reads and break the bytes up on the
\r\n
boundaries.