2013-08-29 127 views
3

我正在为我的iPhone制作一个iOS套接字客户端。我需要通过tcp/ip发送一些字节。总的想法是,我想将多个值存储在单个字节数组中,以避免多次写入流。借此例如:包含整数和字符串表示的字节数组

uint8_t buffer[1024]; // buffer to hold all data I'm sending 

NSString *command = @"Broadcast"; // the actual message i want to send 
int length = [command length]; // length of said message 

现在,对于缓冲器阵列中的第一4个位置,我想提出的长度是可变的,以及从4-13,我想提出实际的消息。我知道如何在服务器端对其进行解码,但我无法弄清楚如何将这些数据存入缓冲区数组,因此我有一个包含所有要发送数据的数组。

任何帮助非常感谢!

回答

2

考虑下面的代码:

// First, we get the C-string (NULL-terminated array of bytes) out of NSString. 
const char *cString = [command UTF8String]; 

// The length of C-string (a number of bytes!) differs terribly from 
// NSString length (number of characters! Unicode characters are 
// of variable length!). 
// So we get actual number of bytes and clamp it to the buffer 
// size (so if the command string occasionally gets larger than our 
// buffer, it gets truncated). 
size_t byteCount = MIN(BUFFER_SIZE - 4, 
         [command lengthOfBytesUsingEncoding:NSUTF8StringEncoding]); 

// Now we're using C type conversion to reinterpret the buffer as a 
// pointer to int32_t. The buffer points to some memory, it's up to us 
// how to treat it. 
*(int32_t *)buffer = byteCount; 

// And finally we're copying our string bytes to the rest of the buffer. 
memcpy(buffer + 4, cString, byteCount); 

有这个代码一个警告 - 它采用主机字节顺序存储uint32_t变量,因此,如果你通过网络传递这个缓冲区,通常是一个好主意,使你的字节顺序是固定的(网络历史上采用大字节序,尽管大多数计算机现在是小端)。

要解决的字节顺序只需更换线

*(int32_t *)buffer = byteCount; 

*(int32_t *)buffer = htonl(byteCount); 

而且不要忘了字节顺序转换回处理其他计算机上该缓冲区的时候!

+0

看来你的答案对我来说很重要,但是我很难理解它的实际功能。你介意可扩展的例子吗?比如说我想把一个消息的长度附加到缓冲区的末尾,并在那之后追加消息,我该如何去做这件事? –

+0

@ cnh1991我已将评论添加到我的代码中。希望能帮助到你。 – iHunter

+0

@ cnh1991如果您想在缓冲区的最后写入长度,则会执行以下代码:'*(uint32_t *)(buffer + 1020)= byteCount'。它重新解释'buffer + 1020',例如作为指向'uint32_t'的指针,从'buffer'开始的1020个字符。 – iHunter

0

你可以把它作为C字符串:

const char * cString = [command UTF8String]; 
length = strlen(cString); 

for (int i = 0; i < length; ++i) { 
    buffer[i + 4] = cString[i]; 
} 

buffer[0] = length & 0xff; 
buffer[1] = (length >> 8) & 0xff; 
buffer[2] = (length >> 16) & 0xff; 
buffer[3] = (length >> 24) & 0xff; 
+0

这将命令字符串添加到缓冲区,就像我需要的是。但是,我如何在缓冲区的前4个元素中放置字符串长度的字节表示? –

+0

添加用于将长度放在前4个字节中的代码。 – Kirsteins

+0

如果使用非ASCII字符,此代码将会中断 - '[NSString length]'返回字符数,而不是字节数。 – iHunter

0

这不是生产代码,如果尺寸很大并且没有错误检查,它会溢出。应该给你一个什么需要做的想法。

const int SIZE = 64; 
const int SIZE_OFFSET = 0; 
const int MESSAGE_OFFSET = 4; 


// Set up the buffer. 
Byte buffer[SIZE]; 
for (int i = 0; i < SIZE; i++) { 
    buffer[i] = 0; 
} 
uint8 *ptr; // Used to traverse data. 

NSString *command= @"Broadcast"; 

// note: non ASCII characters, such as é, will consume 2 bytes. 
NSData *data = [command dataUsingEncoding:NSUTF8StringEncoding]; 
// uint32 ensures we get a 4 byte integer on non 32bit systems. 
uint32 dataLength = [data length] ; // Number of bytes stored in data. 

// Place dataLength into the first 4 elements of the buffer. Keep endianness in mind. 
*ptr = &dataLength; 
for (int8_t iterator = SIZE_OFFSET; iterator < sizeof(uint32) + SIZE_OFFSET; iterator++) { 
    buffer[iterator] = ptr[iterator]; 
} 

// todo, place data into buffer. 
+0

为什么不使用'memset'来清零缓冲区和'memcpy'来将字符串复制到缓冲区? – iHunter

+0

我忘了那两个!谢谢你的提醒! –