Hello. I use my iOS application to download big text files from the server over TCP. This is the code I use:
func openNetworkCommunication()
{
if(self.inputStream != nil && self.outputStream != nil)
{
closeNetworkCommunication()
}
let ipAddress = delegate?.ipAddressString as! CFStringRef
let portNumber = delegate?.ipPort
var readStream: Unmanaged<CFReadStream>?
var writeStream: Unmanaged<CFWriteStream>?
CFStreamCreatePairWithSocketToHost(nil, ipAddress, portNumber!, &readStream, &writeStream)
self.inputStream = readStream!.takeRetainedValue()
self.outputStream = writeStream!.takeRetainedValue()
self.outputBuffer = delegate?.messageToServer.dataUsingEncoding(NSUTF8StringEncoding) as? NSMutableData
self.inputStream?.delegate = self
self.outputStream?.delegate = self
self.inputStream?.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
self.outputStream?.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
self.inputStream?.open()
self.outputStream?.open()
}
func closeNetworkCommunication()
{
self.inputStream?.close()
self.outputStream?.close()
self.inputStream?.removeFromRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
self.outputStream?.removeFromRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
self.inputStream?.delegate = nil
self.outputStream?.delegate = nil
self.inputStream = nil;
self.outputStream = nil;
self.outputBuffer = nil;
}
func stream(theStream : NSStream, handleEvent streamEvent : NSStreamEvent)
{
switch (streamEvent)
{
case NSStreamEvent.None:
println("NSStreamEventNone")
case NSStreamEvent.OpenCompleted:
println("NSStreamEventOpenCompleted")
case NSStreamEvent.HasBytesAvailable:
println("NSStreamEvent.HasBytesAvailable")
var buffer = [UInt8](count: 4096, repeatedValue: 0)
if ( theStream == self.inputStream)
{
while (self.inputStream!.hasBytesAvailable)
{
var len = inputStream!.read(&buffer, maxLength: buffer.count)
if len < 0
{
self.error = self.inputStream!.streamError
println("Input stream has less than 0 bytes")
closeNetworkCommunication()
}
else if len == 0
{
println("Input stream has 0 bytes")
closeNetworkCommunication()
}
if(len > 0)
{
var messageFromServer = NSString(bytes: &buffer, length: buffer.count, encoding: NSUTF8StringEncoding)
delegate?.messageReceived(messageFromServer!)
}
}
}
case NSStreamEvent.HasSpaceAvailable:
println("NSStreamEventHasSpaceAvailable")
if self.outputBuffer?.length != 0
{
var bytesWritten : Int = self.outputStream!.write(UnsafePointer<UInt8>(self.outputBuffer.bytes), maxLength: self.outputBuffer.length)
if bytesWritten <= 0
{
self.error = self.outputStream?.streamError
}
else
{
self.outputBuffer?.replaceBytesInRange(NSMakeRange(0, bytesWritten), withBytes: nil, length: 0)
}
}
case NSStreamEvent.ErrorOccurred:
println("NSStreamEventErrorOccurred");
case NSStreamEvent.EndEncountered:
println("NSStreamEventEndEncountered")
theStream.close()
theStream.removeFromRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
default:
println("Unknown event")
}
}
I have two big problems:
1) After the text has been transmitted to the iOS client, the connection remains open. If I try to do closeNetworkCommunication() in NSStreamEvent.HasBytesAvailable, then not the whole text is downloaded -- it is truncated in the middle. Is there a way to close the connection only after the full text has been passed?
2) Sometimes, the text passed to the iOS application includes a piece from the beginning of the text. For example:
Original:
AAAAAAAAAAAAAA
BBBBBBBBBBBBBB
Passed:
AAAAAAAAAAAAAA
BBBBBBBBBBBBBBAAAA
I am checking what is transmitted by the server and it is the original text... Does the code in the client fills the buffer with the remaining text to have the full size buffer? And how to fix it?
Many thanks!