Frage

I'm making an iOS socket client for my iPhone. I need to send some bytes through tcp/ip. The general idea is, that I want to store multiple values in a single byte array, to avoid several writes to the stream. Take this example:

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

Now, for the first 4 positions in the buffer array, i want to put the length variable, and from 4-13, i want to put the actual message. I know how to decode it on the server end, but I can't quite figure out how to get this data into the buffer array, so I have one array with all the data I want to send.

Any help much appreciated!

War es hilfreich?

Lösung

Consider the following code:

// 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); 

There's a caveat in this code - it uses host byte order to store uint32_t variable, so if you're passing this buffer over network, it's generally a good idea to make your byte order fixed (networking historically employs big-endianness, though most of the computers are nowadays little-endian).

To fix the byte order just replace the line

*(int32_t *)buffer = byteCount;

with

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

And don't forget to convert byte ordering back when processing this buffer on other computer!

Andere Tipps

You can send it as C string:

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;

This is NOT production code, it overflows if size large and lacks error checks. Should give you an idea of what needs to be done.

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.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top