NSMutableData 到 UnsafeMutableRawPointer 的字节不更新 mutableData 的值
NSMutableData's bytes to UnsafeMutableRawPointer not updating the value of mutableData
我有一个结构对象。和一个方法,其输入是有效载荷。现在我正在创建一个名为 packet
的可变数据,它的可变字节指的是 ICMPHeader 结构。
struct ICMPHeader {
var type:UInt8
var code:UInt8
var checksum:UInt16
var identifier:UInt16
var sequenceNumber:UInt16
};
func createPacket(payload:NSData) -> NSData(){
var packet:NSMutableData?
var icmpPtr:ICMPHeader = ICMPHeader(type: 0, code: 0, checksum: 0, identifier: 0, sequenceNumber: 0)
packet = NSMutableData(length: Int(MemoryLayout<ICMPHeader>.size + payload.length))
if packet != nil {
icmpPtr = packet!.mutableBytes.assumingMemoryBound(to: ICMPHeader.self).pointee
icmpPtr.type = type
icmpPtr.code = 0
icmpPtr.checksum = 0
icmpPtr.identifier = CFSwapInt16BigToHost(identifier)
icmpPtr.sequenceNumber = CFSwapInt16HostToBig(identifier)
memcpy(&icmpPtr + 1, payload.bytes, payload.length)
if (requiresChecksum) {
icmpPtr.checksum = in_cksum(packet!.bytes, bufferLen: packet!.length);
}
}
return packet
}
可变字节已成功绑定到结构,并且结构 ICMPHeader
中的值也已更新。
问题是改变结构中的值并没有改变可变数据的值packet
。
如果我在创建结构后尝试重新创建数据包,那么它就会崩溃。
package = NSMutableData(bytes: unsafeBitCast(icmpPtr, to: UnsafeMutableRawPointer.self), length: Int(MemoryLayout<ICMPHeader>.size + payload.length))
我在 XCode 8.1 Swift 发行说明中找到了答案。
对结构对象进行更改后 icmpPtr
我已将其改回缓冲区指针。
var byteBuffer = [UInt8]()
withUnsafeBytes(of: &icmpPtr) {
(bytes: UnsafeRawBufferPointer) in byteBuffer += bytes
}
package.replaceBytes(in: NSMakeRange(0, byteBuffer.count), withBytes: byteBuffer)
因此,我没有创建新的数据对象,而是替换了字节,效果非常好。
根据文档:
XCode 8.1 Release Notes:
https://developer.apple.com/library/content/releasenotes/DeveloperTools/RN-Xcode/Introduction.html
Swift Section:
A new withUnsafeBytes(of:) function exposes a value's in-memory
representation as an UnsafeRawBufferPointer. This example copies a
heterogenous struct into a homogeneous array of bytes:
struct Header {
var x: Int
var y: Float
}
var header = Header(x: 0, y: 0.0)
var byteBuffer = [UInt8]()
withUnsafeBytes(of: &header) {
(bytes: UnsafeRawBufferPointer) in byteBuffer += bytes
}
A new Array.withUnsafeBytes method exposes an array's underlying
buffer as an UnsafeRawBufferPointer. This example copies an array of
integers into an array of bytes:
let intArray = [1, 2, 3]
var byteBuffer = [UInt8]()
intArray.withUnsafeBytes {
(bytes: UnsafeRawBufferPointer) in byteBuffer += bytes
}
所以最终实现是
struct ICMPHeader {
var type:UInt8
var code:UInt8
var checksum:UInt16
var identifier:UInt16
var sequenceNumber:UInt16
};
func createPacket(payload:NSData) -> NSData(){
var packet:NSMutableData?
var icmpPtr:ICMPHeader = ICMPHeader(type: 0, code: 0, checksum: 0, identifier: 0, sequenceNumber: 0)
packet = NSMutableData(length: Int(MemoryLayout<ICMPHeader>.size + payload.length))
if packet != nil {
icmpPtr = packet!.mutableBytes.assumingMemoryBound(to: ICMPHeader.self).pointee
icmpPtr.type = type
icmpPtr.code = 0
icmpPtr.checksum = 0
icmpPtr.identifier = CFSwapInt16BigToHost(identifier)
icmpPtr.sequenceNumber = CFSwapInt16HostToBig(identifier)
memcpy(&icmpPtr + 1, payload.bytes, payload.length)
if (requiresChecksum) {
icmpPtr.checksum = in_cksum(packet!.bytes, bufferLen: packet!.length);
}
var byteBuffer = [UInt8]()
withUnsafeBytes(of: &icmpPtr) {
(bytes: UnsafeRawBufferPointer) in byteBuffer += bytes
}
packet.replaceBytes(in: NSMakeRange(0, byteBuffer.count), withBytes: byteBuffer)
}
return packet
}
我有一个结构对象。和一个方法,其输入是有效载荷。现在我正在创建一个名为 packet
的可变数据,它的可变字节指的是 ICMPHeader 结构。
struct ICMPHeader {
var type:UInt8
var code:UInt8
var checksum:UInt16
var identifier:UInt16
var sequenceNumber:UInt16
};
func createPacket(payload:NSData) -> NSData(){
var packet:NSMutableData?
var icmpPtr:ICMPHeader = ICMPHeader(type: 0, code: 0, checksum: 0, identifier: 0, sequenceNumber: 0)
packet = NSMutableData(length: Int(MemoryLayout<ICMPHeader>.size + payload.length))
if packet != nil {
icmpPtr = packet!.mutableBytes.assumingMemoryBound(to: ICMPHeader.self).pointee
icmpPtr.type = type
icmpPtr.code = 0
icmpPtr.checksum = 0
icmpPtr.identifier = CFSwapInt16BigToHost(identifier)
icmpPtr.sequenceNumber = CFSwapInt16HostToBig(identifier)
memcpy(&icmpPtr + 1, payload.bytes, payload.length)
if (requiresChecksum) {
icmpPtr.checksum = in_cksum(packet!.bytes, bufferLen: packet!.length);
}
}
return packet
}
可变字节已成功绑定到结构,并且结构 ICMPHeader
中的值也已更新。
问题是改变结构中的值并没有改变可变数据的值packet
。
如果我在创建结构后尝试重新创建数据包,那么它就会崩溃。
package = NSMutableData(bytes: unsafeBitCast(icmpPtr, to: UnsafeMutableRawPointer.self), length: Int(MemoryLayout<ICMPHeader>.size + payload.length))
我在 XCode 8.1 Swift 发行说明中找到了答案。
对结构对象进行更改后 icmpPtr
我已将其改回缓冲区指针。
var byteBuffer = [UInt8]()
withUnsafeBytes(of: &icmpPtr) {
(bytes: UnsafeRawBufferPointer) in byteBuffer += bytes
}
package.replaceBytes(in: NSMakeRange(0, byteBuffer.count), withBytes: byteBuffer)
因此,我没有创建新的数据对象,而是替换了字节,效果非常好。
根据文档:
XCode 8.1 Release Notes: https://developer.apple.com/library/content/releasenotes/DeveloperTools/RN-Xcode/Introduction.html Swift Section:
A new withUnsafeBytes(of:) function exposes a value's in-memory representation as an UnsafeRawBufferPointer. This example copies a heterogenous struct into a homogeneous array of bytes:
struct Header { var x: Int var y: Float } var header = Header(x: 0, y: 0.0) var byteBuffer = [UInt8]() withUnsafeBytes(of: &header) { (bytes: UnsafeRawBufferPointer) in byteBuffer += bytes }
A new Array.withUnsafeBytes method exposes an array's underlying buffer as an UnsafeRawBufferPointer. This example copies an array of integers into an array of bytes:
let intArray = [1, 2, 3] var byteBuffer = [UInt8]() intArray.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in byteBuffer += bytes }
所以最终实现是
struct ICMPHeader {
var type:UInt8
var code:UInt8
var checksum:UInt16
var identifier:UInt16
var sequenceNumber:UInt16
};
func createPacket(payload:NSData) -> NSData(){
var packet:NSMutableData?
var icmpPtr:ICMPHeader = ICMPHeader(type: 0, code: 0, checksum: 0, identifier: 0, sequenceNumber: 0)
packet = NSMutableData(length: Int(MemoryLayout<ICMPHeader>.size + payload.length))
if packet != nil {
icmpPtr = packet!.mutableBytes.assumingMemoryBound(to: ICMPHeader.self).pointee
icmpPtr.type = type
icmpPtr.code = 0
icmpPtr.checksum = 0
icmpPtr.identifier = CFSwapInt16BigToHost(identifier)
icmpPtr.sequenceNumber = CFSwapInt16HostToBig(identifier)
memcpy(&icmpPtr + 1, payload.bytes, payload.length)
if (requiresChecksum) {
icmpPtr.checksum = in_cksum(packet!.bytes, bufferLen: packet!.length);
}
var byteBuffer = [UInt8]()
withUnsafeBytes(of: &icmpPtr) {
(bytes: UnsafeRawBufferPointer) in byteBuffer += bytes
}
packet.replaceBytes(in: NSMakeRange(0, byteBuffer.count), withBytes: byteBuffer)
}
return packet
}