к большему значению, которое добавляет ноль байтов. - Возможно, вы все равно захотите проверить максимальное значение, иначе система может попытаться выделить много ГБ, если поступят неверные данные.
я есть сервер, который отправляет мне сообщения по TCP, где первые 4 байта определяют длину остальной части сообщения. Так что мне нужно
1) прочитать 4 байта в UInt32 (работает) и сохранить его вbytes_expected
2) читатьbytes_expected байтов всообщение
Прямо сейчас мой код выглядит так:
private let inputStreamAccessQueue = DispatchQueue(label: "SynchronizedInputStreamAccess")
func inputStreamHandler(_ event: Stream.Event) {
switch event {
case Stream.Event.hasBytesAvailable:
self.handleInput()
...
}
}
func handleInput() {
// **QUESTION: Do I use this barrier wrong?**
self.inputStreamAccessQueue.sync(flags: .barrier) {
guard let istr = self.inputStream else {
log.error(self.buildLogMessage("InputStream is nil"))
return
}
guard istr.hasBytesAvailable else {
log.error(self.buildLogMessage("handleInput() called when inputstream has no bytes available"))
return
}
let lengthbuffer = UnsafeMutablePointer<UInt8>.allocate(capacity: 4)
defer { lengthbuffer.deallocate(capacity: 4) }
let lenbytes_read = istr.read(lengthbuffer, maxLength: 4)
guard lenbytes_read == 4 else {
self.errorHandler(NetworkingError.InputError("Input Stream received \(lenbytes_read) (!=4) bytes"))
return
}
let bytes_expected = Int(UnsafeRawPointer(lengthbuffer).load(as: UInt32.self).bigEndian)
log.info(self.buildLogMessage("expect \(bytes_expected) bytes"))
print("::DEBUG", call, "bytes_expected", bytes_expected)
var message = ""
var bytes_missing = bytes_expected
while bytes_missing > 0 {
//print("::DEBUG", call, "bytes_missing", bytes_missing)
let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bytes_missing)
let bytes_read = istr.read(buffer, maxLength: bytes_missing)
print("::DEBUG", call, "bytes_read", bytes_read)
guard bytes_read > 0 else {
print("bytes_read not > 0: \(bytes_read)")
return
}
guard bytes_read <= bytes_missing else {
print("Read more bytes than expected. missing=\(bytes_missing), read=\(bytes_read)")
return
}
guard let partial_message = String(bytesNoCopy: buffer, length: bytes_read, encoding: .utf8, freeWhenDone: true) else {
log.error("ERROR WHEN READING")
return
}
message = message + partial_message
bytes_missing -= bytes_read
}
self.handleMessage(message)
}
}
Моя проблема в том, что istr.read (buffer, maxLength: bytes_missing) иногда не читает все сообщения сразу, поэтому я зацикливаюсь, пока не прочитаю все, что хочу. Но я все еще вижу сбой моего приложения (редко), потому что handleInput () вызывается снова, пока еще выполняется другой вызов этого метода. В этом случае bytes_expected содержит случайные значения, и приложение вылетает из-за неправильного выделения памяти.
Я думал, что смогу избежать этого, используя барьер. Но, похоже, это не работает ... Я неправильно использую барьер?