简体   繁体   中英

Get the content length from first two bytes of modified Java UTF (created using java writeUTF() method) in swift

I am using GCDAsyncSocket to create a TCP client on iOS (using swift). The client is communicating with a TCP server written in JAVA. The data is written to to the socket using the JAVA's writeUtf() method. So to read the data on the TCP client, I need to know the length of the data available on the socket. The java UTF format is different from standard UTF and encodes the length of the content in first 2 bytes of data. The length of the incoming data must be known to read the data in GCDAsyncSocket.

Questions:

  1. How to get the size of incoming data from the first two bytes of modified UTF-8 in swift?

  2. Is there any better way to read the data from java writeUTF() by detecting the end of the stream?

I was using my own getJavaUTFFrom function to read utf from java server tcp socket. firstly you should get data from tcp socket to NSMutableData and transform its content to string with getJavaUTFFrom.

@discardableResult func getJavaUTFFrom(_ data: NSMutableData, location: Int, toStr: inout String)->Int! {

    var utfLength: Int = 0

    //getJavaCharFrom reads utf string length
    getJavaCharFrom(data, location: location, toIntVar: &utfLength)


    if location + utfLength - 1 > data.length {
        print("out of message body range getJavaUTFFrom at location: \(location)")

        return nil 

    }


    var buff = [UInt8](repeating: 0, count: Int(utfLength))
    data.getBytes(&buff, range: NSRange(location: location+MemoryLayout<UInt16>.size, length: Int(utfLength)))
    toStr = String(bytes: buff, encoding: String.Encoding.utf8)!
    return location + MemoryLayout<UInt16>.size + utfLength //returning java modified utf8 string length
}

@discardableResult func getJavaCharFrom(_ data: NSMutableData, location: Int, toIntVar: inout Int)->Int! {

    if location + MemoryLayout<UInt16>.size-1 > data.length {
        print("out of message body range getJavaCharFrom")
        return nil
    }

    var tmp = UInt16(0)
    data.getBytes(&tmp, range: NSRange(location: location, length: MemoryLayout<UInt16>.size))
    toIntVar=Int(tmp.bigEndian)
    return location + MemoryLayout<UInt16>.size
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM