Ios 在Swift 4中从InputStream读取n个字节
我有一个通过TCP向我发送消息的服务器,其中前4个字节决定消息其余部分的长度。所以我需要 1) 将4个字节读入UInt32(works),并将其存储到预期的字节中 2) 将字节\预期字节读入消息 现在,我的代码如下所示: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
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
}
}