我是Objective C的新手,正在为发送UDP数据包的Titanium框架修改iOS模块。该模块当前允许您传入要发送的文本字符串,并将其转换为字节并通过UDP将其发送到目标IP和端口。这很好用,这是代码:
https://github.com/chrisfjones/titanium_module_udp/blob/master/UDPSocketProxy.m
我想要做的是将一个字节数组传递给send函数而不是字符串,并让它发送它。这是Titanium代码:
var udp = require('chrisfjones.titanium_module_udp');
var socket = udp.createUDP();
var bytes = [ 100, 15, 132, 53, 14, 246, 0, 0, 0, 0, 196, 209, 1, 1, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 16, 0, 45, 120, 0, 0, 0, 0, 158, 4, 111, 30, 179, 41 ];
socket.send(bytes, "1.2.3.4", 6100);
到目前为止,这是新的发送功能:
- (void) sendBytes: (NSArray*) args {
NSArray *msg = (NSArray*)[args objectAtIndex: 0];
NSString *host = [TiUtils stringValue:[args objectAtIndex: 1]];
NSInteger port = [TiUtils intValue: [args objectAtIndex: 2]];
NSLog(@"%@ send bytes: %@ to %@:%i", self, msg, host, port);
struct sockaddr_in destinationAddress;
socklen_t sockaddr_destaddr_len = sizeof(destinationAddress);
memset(&destinationAddress, 0, sockaddr_destaddr_len);
destinationAddress.sin_len = (__uint8_t) sockaddr_destaddr_len;
destinationAddress.sin_family = AF_INET;
destinationAddress.sin_port = htons(port);
destinationAddress.sin_addr.s_addr = inet_addr([host cStringUsingEncoding: NSUTF8StringEncoding]);
NSData *destinationAddressData = [NSData dataWithBytes:&destinationAddress length:sizeof(destinationAddress)];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:msg];
CFSocketError socket_error = CFSocketSendData(_socket, (CFDataRef) destinationAddressData, (CFDataRef) data, 10);
if (socket_error) {
NSLog(@"socket error: %li", socket_error);
} else {
NSLog(@"sent bytes: '%@' to %@:%i", msg, host, port);
}
}
你会注意到它传入NSArray。这是因为Titanium将我创建的javascript数组转换为NSNumber对象的NSArray。我读到这是非常低效的,但是它内置于Titanium框架中,所以我没有看到它的方法,所以我希望得到一个答案,如何使它工作与这传入,而不是如何讲述如何效率低下。
当我调用新的send方法时,而不是发送我传入的大约50个字节,我可以在wireshark中看到它实际上传递超过1000个字节。我假设问题在于此行的转换:
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:msg];
有人可以请教如何发送我传入的字节数组吗?谢谢!
答案 0 :(得分:3)
是的,在这种情况下你不想使用归档器,因为你只是试图将一组字节变成NSData
的块。根据您是传入NSNumber
数组还是NSString
数组,您基本上需要遍历数组的内容并将数据附加到NSMutableData
。
假设它是NSNumber
的数组,那么这样的东西应该有用:
NSMutableData *data = [[NSMutableData alloc] initWithCapacity: [msg count]];
for( NSNumber *number in msg) {
char byte = [number charValue];
[data appendBytes: &byte length: 1];
}
// .... code that uses data ...
[data release];
如果数字是字符串形式的数字值,您可能希望使用-(int)intValue
NSString
方法提取数据,然后将其添加到数据中,基本上改变了上述内容到:
NSMutableData *data = [[NSMutableData alloc] initWithCapacity: [msg count]];
for( NSString *string in msg) {
char byte = (char)[string intValue];
[data appendBytes: &byte length: 1];
}
// .... code that uses data ...
[data release];
而且,如果你试图填充字符串中的字符,那么你需要使用[string characterAtIndex: 0]
来抓取字符,并补偿你将收到unichar
的事实一个char
。
答案 1 :(得分:0)
- (NSData *)byteArray2Data:(NSArray *)array {
NSMutableData *data = [NSMutableData data];
[array enumerateObjectsUsingBlock:^(NSNumber* number, NSUInteger index, BOOL* stop) {
uint8_t tmp = number.unsignedCharValue;
[data appendBytes:(void *)(&tmp)length:1];
}];
return data;
}
- (NSArray *)byteData2Array:(NSData *)data {
NSMutableArray *array = [[NSMutableArray alloc] init];
[data enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) {
unsigned char *dataBytes = (unsigned char*)bytes;
for (NSInteger i = 0; i < byteRange.length; i++) {
[array addObject:[NSNumber numberWithInt:(dataBytes[i]) & 0xff]];
}
}];
return array;
}