Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 在Swift 4中从InputStream读取n个字节_Ios_Swift_Tcp_Network Programming_Inputstream - Fatal编程技术网

Ios 在Swift 4中从InputStream读取n个字节

Ios 在Swift 4中从InputStream读取n个字节,ios,swift,tcp,network-programming,inputstream,Ios,Swift,Tcp,Network Programming,Inputstream,我有一个通过TCP向我发送消息的服务器,其中前4个字节决定消息其余部分的长度。所以我需要 1) 将4个字节读入UInt32(works),并将其存储到预期的字节中 2) 将字节\预期字节读入消息 现在,我的代码如下所示: private let inputStreamAccessQueue = DispatchQueue(label: "SynchronizedInputStreamAccess") func handleInput(){ //**问题:我是否错误地使用了此屏障** se

我有一个通过TCP向我发送消息的服务器,其中前4个字节决定消息其余部分的长度。所以我需要

1) 将4个字节读入UInt32(works),并将其存储到预期的字节中

2) 将字节\预期字节读入消息

现在,我的代码如下所示:

private let inputStreamAccessQueue  = DispatchQueue(label: "SynchronizedInputStreamAccess")


func handleInput(){
//**问题:我是否错误地使用了此屏障**
self.inputStreamAccessQueue.sync(标志:。屏障){
guard let istr=self.inputStream-else{
log.error(self.buildLogMessage(“InputStream为nil”))
返回
}
防护装置istr.HASBYTES是否可用{
错误(self.buildLogMessage(“当inputstream没有可用字节时调用handleInput()))
返回
}
let lengthbuffer=UnsafemeutablePointer.allocate(容量:4)
延迟{lengthbuffer.deallocate(容量:4)}
让lenbytes_read=istr.read(lengthbuffer,maxLength:4)
保护lenbytes_read==4其他{
self.errorHandler(NetworkingError.InputError(“接收到的输入流\(lenbytes\u read)(!=4)字节”))
返回
}
let bytes_expected=Int(UnsafeRawPointer(lengthbuffer).load(as:UInt32.self).bigEndian)
log.info(self.buildLogMessage(“expect\(bytes\u expected)bytes”))
打印(“::DEBUG”,调用“预期字节数”,预期字节数)
var message=“”
var bytes_missing=应为bytes_
而字节_丢失>0{
//打印(“::调试”,调用,“缺少字节”,缺少字节)
let buffer=unsafemeutablepointer.allocate(容量:字节\缺失)
let bytes\u read=istr.read(缓冲区,最大长度:缺少字节)
打印(“::DEBUG”,调用“bytes\u read”,bytes\u read)
保护字节\u读取>0其他{
打印(“字节读取不>0:\(字节读取)”)
返回
}

我的建议是不要反对网络I/O的异步性。 每当
Stream.Event.hasbytes可用时,读取并收集缓冲区中的数据
如果缓冲区包含足够的数据(4个长度字节加上
预期的消息长度),然后处理数据并将其删除。否则不执行任何操作
等待更多的数据

以下(未经测试的)代码用于演示。 它仅显示与此特定问题相关的零件。 为简洁起见,省略了初始化、事件处理程序等

class MessageReader {

    var buffer = Data(count: 1024) // Must be large enough for largest message + 4
    var bytesRead = 0 // Number of bytes read so far

    // Called from `handleInput` with a complete message.
    func processMessage(message: Data) {
        // ...
    }

    // Called from event handler if `Stream.Event.hasBytesAvailable` is signalled.
    func handleInput(istr: InputStream) {
        assert(bytesRead < buffer.count)

        // Read from input stream, appending to previously read data:
        let maxRead = buffer.count - bytesRead
        let amount = buffer.withUnsafeMutableBytes { (p: UnsafeMutablePointer<UInt8>) in
            istr.read(p + bytesRead, maxLength: maxRead)
        }
        guard amount > 0 else {
            // handle EOF or read error ...
            fatalError()
        }
        bytesRead += amount

        while bytesRead >= 4 {
            // Read message size:
            let messageSize = buffer.withUnsafeBytes { (p: UnsafePointer<UInt32>) in
                Int(UInt32(bigEndian: p.pointee))
            }
            let totalSize = 4 + messageSize
            guard totalSize <= buffer.count else {
                // Handle buffer too small for message situation ...
                fatalError()
            }

            if bytesRead < totalSize {
                break // Not enough data to read message.
            }

            // Buffer contains complete message now. Process it ...
            processMessage(message: buffer[4 ..< totalSize])

            // ... and remove it from the buffer:
            if totalSize < bytesRead {
                // Move remaining data to the front:
                buffer.withUnsafeMutableBytes { (p: UnsafeMutablePointer<UInt8>) in
                    _ = memmove(p, p + totalSize, bytesRead - totalSize)
                }
            }
            bytesRead -= totalSize
        }
    }
}
class消息阅读器{
var buffer=Data(计数:1024)//必须足够大,以容纳最大的消息+4
var bytesRead=0//到目前为止读取的字节数
//从“handleInput”调用,并显示完整消息。
func processMessage(消息:数据){
// ...
}
//如果发出“Stream.event.hasBytesAvailable”信号,则从事件处理程序调用。
func handleInput(istr:InputStream){
断言(字节读取0其他{
//处理EOF或读取错误。。。
法塔莱罗()
}
字节读取+=数量
而字节读取>=4{
//读取邮件大小:
让messageSize=buffer.withUnsafeBytes{(p:UnsafePointer)在
Int(UInt32(bigEndian:p.pointee))
}
让totalSize=4+messageSize
guard totalSize灵感来自Martin R(-非常感谢!)我提出了以下解决方案:

var buffer = Data(count: 4096)
var offset = 0 // the index of the first byte that can be overridden
var readState = 0
var missingMsgBytes = 0
var msg = ""

func handleInput(_ istr: InputStream) {
    assert(buffer.count >= 5, "buffer must be large enough to contain length info (4 bytes) and at least one payload byte => min 5 bytes buffer required")
    assert(offset < buffer.count, "offset \(offset) is not smaller than \(buffer.count)")

    let toRead = buffer.count - offset
    let read = buffer.withUnsafeMutableBytes { (p: UnsafeMutablePointer<UInt8>) in istr.read(p + offset, maxLength: toRead) }
    guard read > 0 else {
        self.errorHandler(NetworkingError.InputError("Input Stream received \(read) bytes which is smaller than 0 => Network error"))
        return
    }
    offset += read
    var msgStart = 0
    var msgEnd = 0

    if readState == 0 {
        if offset < 4 {
            return
        }
        missingMsgBytes = buffer[0...3].withUnsafeBytes { (p: UnsafePointer<UInt32>) in Int(UInt32(bigEndian: p.pointee)) }
        msgStart = 4
        msgEnd = offset
        readState = 1
    } else {
        msgStart = 0
        msgEnd = offset
    }

    var fullMessageRead = false

    if readState == 1 {
        let payloadRead = msgEnd - msgStart
        if payloadRead <= missingMsgBytes {
            assert(msgEnd > msgStart, "msgEnd (\(msgEnd) <= msgStart \(msgStart). This should not happen")
            if msgEnd > msgStart {
                msg += String(data: buffer[msgStart..<msgEnd], encoding: .utf8)!
                missingMsgBytes -= payloadRead
                offset = 0
            }
            fullMessageRead = (missingMsgBytes == 0)
        } else { // read more than was missing
            msg += String(data: buffer[msgStart..<msgStart+missingMsgBytes], encoding: .utf8)!
            fullMessageRead = true
            buffer.withUnsafeMutableBytes { (p: UnsafeMutablePointer<UInt8>) in
                _ = memmove(p, p + missingMsgBytes, read - missingMsgBytes) // dst, src, number
            }
            offset = read-missingMsgBytes
        }
    }

    if fullMessageRead {
        handleMessage(msg)
        readState = 0
         msg = ""
        missingMsgBytes = 0
    }
}
var buffer=数据(计数:4096)
var offset=0//可以重写的第一个字节的索引
var readState=0
var missingMsgBytes=0
var msg=“”
func handleInput(uIstr:InputStream){
断言(buffer.count>=5,“缓冲区必须足够大,以包含长度信息(4个字节)和至少一个有效负载字节=>至少需要5个字节的缓冲区”)
断言(偏移量0其他{
self.errorHandler(NetworkingError.InputError(“输入流接收到\(读取)字节,小于0=>网络错误”))
返回
}
偏移量+=读取
var msgStart=0
var msgEnd=0
如果readState==0{
如果偏移量小于4{
返回
}
missingMsgBytes=缓冲区[0…3]。withUnsafeBytes{(p:UnsafePointer)在Int(UInt32(bigEndian:p.pointee))}
msgStart=4
msgEnd=偏移量
readState=1
}否则{
msgStart=0
msgEnd=偏移量
}
var fullMessageRead=false
如果readState==1{
让payloadRead=msgEnd-msgStart

如果payloadRead msgStart,“msgEnd(\(msgEnd)这与吗?是的,但是评论中的一个人告诉我打开一个新问题。我不小心在最后一个问题中使用了一个旧帐户。我删除了旧帐户,并将在将来使用这个帐户。是的,新问题是正确的,我只是想知道不同的用户名。我没有时间写完整的答案,但我建议不要对抗网络IO的异步性质,也不要使用屏障。–在
handleInput()
中,只需收集缓冲区中的可用数据。如果缓冲区包含足够的数据(计数器4字节+预期字节数),处理它并将其从缓冲区中删除。否则,什么也不做,等待更多数据。对不起,我没有使用该库的经验,也没有任何建议。非常感谢!如果我没有找到工作的libI,我将尝试此操作,并收到错误“同时访问0x16584fe0,但mod
class MessageReader {

    var buffer = Data(count: 1024) // Must be large enough for largest message + 4
    var bytesRead = 0 // Number of bytes read so far

    // Called from `handleInput` with a complete message.
    func processMessage(message: Data) {
        // ...
    }

    // Called from event handler if `Stream.Event.hasBytesAvailable` is signalled.
    func handleInput(istr: InputStream) {
        assert(bytesRead < buffer.count)

        // Read from input stream, appending to previously read data:
        let maxRead = buffer.count - bytesRead
        let amount = buffer.withUnsafeMutableBytes { (p: UnsafeMutablePointer<UInt8>) in
            istr.read(p + bytesRead, maxLength: maxRead)
        }
        guard amount > 0 else {
            // handle EOF or read error ...
            fatalError()
        }
        bytesRead += amount

        while bytesRead >= 4 {
            // Read message size:
            let messageSize = buffer.withUnsafeBytes { (p: UnsafePointer<UInt32>) in
                Int(UInt32(bigEndian: p.pointee))
            }
            let totalSize = 4 + messageSize
            guard totalSize <= buffer.count else {
                // Handle buffer too small for message situation ...
                fatalError()
            }

            if bytesRead < totalSize {
                break // Not enough data to read message.
            }

            // Buffer contains complete message now. Process it ...
            processMessage(message: buffer[4 ..< totalSize])

            // ... and remove it from the buffer:
            if totalSize < bytesRead {
                // Move remaining data to the front:
                buffer.withUnsafeMutableBytes { (p: UnsafeMutablePointer<UInt8>) in
                    _ = memmove(p, p + totalSize, bytesRead - totalSize)
                }
            }
            bytesRead -= totalSize
        }
    }
}
var buffer = Data(count: 4096)
var offset = 0 // the index of the first byte that can be overridden
var readState = 0
var missingMsgBytes = 0
var msg = ""

func handleInput(_ istr: InputStream) {
    assert(buffer.count >= 5, "buffer must be large enough to contain length info (4 bytes) and at least one payload byte => min 5 bytes buffer required")
    assert(offset < buffer.count, "offset \(offset) is not smaller than \(buffer.count)")

    let toRead = buffer.count - offset
    let read = buffer.withUnsafeMutableBytes { (p: UnsafeMutablePointer<UInt8>) in istr.read(p + offset, maxLength: toRead) }
    guard read > 0 else {
        self.errorHandler(NetworkingError.InputError("Input Stream received \(read) bytes which is smaller than 0 => Network error"))
        return
    }
    offset += read
    var msgStart = 0
    var msgEnd = 0

    if readState == 0 {
        if offset < 4 {
            return
        }
        missingMsgBytes = buffer[0...3].withUnsafeBytes { (p: UnsafePointer<UInt32>) in Int(UInt32(bigEndian: p.pointee)) }
        msgStart = 4
        msgEnd = offset
        readState = 1
    } else {
        msgStart = 0
        msgEnd = offset
    }

    var fullMessageRead = false

    if readState == 1 {
        let payloadRead = msgEnd - msgStart
        if payloadRead <= missingMsgBytes {
            assert(msgEnd > msgStart, "msgEnd (\(msgEnd) <= msgStart \(msgStart). This should not happen")
            if msgEnd > msgStart {
                msg += String(data: buffer[msgStart..<msgEnd], encoding: .utf8)!
                missingMsgBytes -= payloadRead
                offset = 0
            }
            fullMessageRead = (missingMsgBytes == 0)
        } else { // read more than was missing
            msg += String(data: buffer[msgStart..<msgStart+missingMsgBytes], encoding: .utf8)!
            fullMessageRead = true
            buffer.withUnsafeMutableBytes { (p: UnsafeMutablePointer<UInt8>) in
                _ = memmove(p, p + missingMsgBytes, read - missingMsgBytes) // dst, src, number
            }
            offset = read-missingMsgBytes
        }
    }

    if fullMessageRead {
        handleMessage(msg)
        readState = 0
         msg = ""
        missingMsgBytes = 0
    }
}