daltoniam / Starscream

Websockets in swift for iOS and OSX
Apache License 2.0
8.37k stars 1.21k forks source link

Is it possible to send/write byte array [][UInt8], using this library #870

Open anoopmg opened 3 years ago

anoopmg commented 3 years ago

Server accept byte array ([UInt8]) in socket communication. is it possible to send byte array from ios client using starscream framework

msonnino commented 3 years ago

+1 I'm stuck on this as well.

EDIT: I found this: https://stackoverflow.com/questions/43838646/swift-writing-binary-directly-like-python Haven't had time to test it yet though. I'll update.

msonnino commented 3 years ago

Hi, I figured it out eventually, hope it helps anyone:

let messageString = "some string to send" //We start with the string we want to send over the socket
let messageBytes = messageString.utf8 //convert it to Bytes
let messageBytesArr = [UInt8](messageBytes) //Convert it to a Bytes Array
let messageData = Data(messageBytesArr) //Convert the array to Data Type

//And finally send it
if let sock = Socket {
    sock.write(data: messageData)
}
mmdock commented 3 years ago

Idk if this would help anyone, but I wrote a simple WebsocketDataHeader class that I use to prepend some additional information when sending messages. For instance, a "tag" value so that I know how to identify when the message is received successfully when the websocket broadcasts a message with that tag.


class WebSocketDataHeader {
    var data: [UInt8] = [] // default to zero header size

    init?(content: Any) {
        guard let json = JSONSerializer.serialize(content) else { return nil }
        let contentByteArray: [UInt8] = Array(json.utf8)
        let sizeDescriptor: UInt32 = UInt32(truncatingIfNeeded: contentByteArray.count)
        guard sizeDescriptor == contentByteArray.count else {
            return nil
        }

        let sizeDescriptorByteArray: [UInt8] = sizeDescriptor.toBytes

        data.append(contentsOf: sizeDescriptorByteArray)
        data.append(contentsOf: contentByteArray)

    }

    func asData() -> Data{
        return Data(data)
    }
}

protocol UIntToUInt8Convertable {
    var toBytes: [UInt8] { get }
}

extension UIntToUInt8Convertable {
    func toByteArr<T: UnsignedInteger>(endian: T, count: Int) -> [UInt8] {
        var _endian = endian
        let bytePtr = withUnsafePointer(to: &_endian) {
            $0.withMemoryRebound(to: UInt8.self, capacity: count) {
                UnsafeBufferPointer(start: $0, count: count)
            }
        }
        return [UInt8](bytePtr)
    }
}

extension UInt32: UIntToUInt8Convertable {
    var toBytes: [UInt8] {
        return toByteArr(endian: self.bigEndian,
                         count: MemoryLayout<UInt32>.size)
    }
}

simple use case:

    @discardableResult
    public func write(_ content: Data, with header: Any) -> Bool{
        guard let socket = webSocket, self.isConnected else {
            if debug { print("websocket failed to write data content")}
            return false
        }
        guard let dataHeader = WebSocketDataHeader(content: header) else {
            if debug { print("websocket failed to convert header data")}
            return false
        }
        var sendData: Data = dataHeader.asData()
        sendData.append(content)

        socket.write(data: sendData)
        if debug { print("websocket attempts to write: \(sendData)")}
        return true
    }

//Sending image message in a chat
let header = ["tag": tag]
insertMessage(message) //Display message visually 
if let imageData = img.uploadData(), let manager = socketManager, manager.write(imageData, with: header){
    //successfully sent message
}
canry41341 commented 3 years ago

Hi, I figured it out eventually, hope it helps anyone:

let messageString = "some string to send" //We start with the string we want to send over the socket
let messageBytes = messageString.utf8 //convert it to Bytes
let messageBytesArr = [UInt8](messageBytes) //Convert it to a Bytes Array
let messageData = Data(messageBytesArr) //Convert the array to Data Type

//And finally send it
if let sock = Socket {
    sock.write(data: messageData)
}

Hi there, i'm having the same issue as your's before, so i'm wondering if this answer is working or not?

msonnino commented 3 years ago

Hi, I figured it out eventually, hope it helps anyone:

let messageString = "some string to send" //We start with the string we want to send over the socket
let messageBytes = messageString.utf8 //convert it to Bytes
let messageBytesArr = [UInt8](messageBytes) //Convert it to a Bytes Array
let messageData = Data(messageBytesArr) //Convert the array to Data Type

//And finally send it
if let sock = Socket {
    sock.write(data: messageData)
}

Hi there, i'm having the same issue as your's before, so i'm wondering if this answer is working or not?

Yes. I've implemented it this way and it worked for me.