2013-08-29 175 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

我忘了那兩個!謝謝你的提醒! –