How to quickly find the mismatch pattern in C - c

Pre-condition:
I can't use malloc.
The error will happen within two bytes, means I can search word by word.
My CPU is 32bit ARM11, no OS during this time.
The first two bytes are important, if first two bytes are 0x00, that means all the rest of the bytes should be 0x00.
If first two bytes are 0xFF, all the rest of the bytes should be 0xFF.
If first two byte are not both 0x0000 and 0xFFFF, I just report an error, no need compare the rest.
I read 256Kbyte block data, which should only have two states:
all 0xFF
all 0x00
However, some data may change to a non-predictable value. I need find them out. I can search it one byte by one byte but seems too slow, so I decided to use dichotomy way to do it — which looks like:
divide read out data into equal half, then compare.
if both are not equal to all 0 or F, it means the data is corrupt at both side and I just need to find the earliest one, so I should give up the 2nd part and just divide the first part again. If only one side has problem, just give up the good one and focus on the problematic on.e
loop above idea
seems after 17 time, should find the point.
How to write the code into loop? Do I need 17 different reference static data with different sizes and to use memcmp?
My current code looks like:
unsigned char gReferData1[2] = {0xFF, 0xFF};
unsigned char gReferData2[2] = {0x00, 0x00};
int main(void)
{
int i = 0, result1 = 0, result2 =0;
read_somewhere(readBuff, sizeof(readBuff)); //read out data
//first test first two bytes
result1 = memcmp(gReferData1, readBuff, 2); //test if 0xFFFF
result2 = memcmp(gReferData2, readBuff, 2); //test if 0x0000
if(result1 == 0)
{
// means all rest data should be 0xFF
for(i=2; i<(0x40000/2); i++)
{
result1 = memcmp(gReferData1, readBuff + offet, 2); //test if 0xFFFF
if(result1 != 0)
{
//means find
// do error handle
}
offset+=2;
}
}
else if(result2 == 0)
{
// means all rest data should be 0x00
for(i=2; i<(0x40000/2); i++)
{
result2 = memcmp(gReferData2, readBuff + offet, 2); //test if 0x0000
if(result2 != 0)
{
//means find
// do error handle
}
offset+=2;
}
}
else
{
//just error
// do error handle
}
return 0;
}

In order to find a defect at a random position you will need to examine each byte at least once. There is no algorithm faster than O(n) for this.
However, your proposed algorithm requires to examine each byte more than once. In order to "divide read out data into equal half, then compare", you will have to read every byte. This is what memcmp will do internally: loop through both memory segments from start to finish until there is a discepancy. It isn't magic. It can't do that any more efficiently than you could with a simple loop.
An optimization which might speed this up (test and measure it!) could be to not go through your data-array byte-by-byte but in steps of sizeof(long) and then cast that segment to long before you compare it. This makes use of the fact that on many 32bit CPUs (not all, test and measure it!) it doesn't take more time to compare two 32bit values than it takes to compare two 8bit values.

You need to check that no byte of that buffer has an illegal state, so you have to check each byte at least once.
On most systems, jumping around is expensive, and reading bytes sequentially is less expensive than anything. So I'd use the more sequential reads possible.
One thing you might try to do is to read the whole buffer sequentially and compare each entry with that of the previous entry, "entry" being a byte or a 16, 32, or 64-bit word, depending on which is faster:
DATATYPE previous = *bufptr;
for (i = 1; i < (length of buffer divided by DATATYPE size); i++) {
if (previous != *(bufptr++)) {
break;
}
}
if (i != (length of buffer divided by DATATYPE size)) {
// There has been an error.
}
// Verify that previous is either 0 or the appropriate number of 0xF's.
Another possibility is to run a memcmp() between the first half of the buffer and the second half of the buffer, then (just for the lols) verify that the first byte is indeed either 0x00 or 0xFF. This fails if two bits in the same relative positions in the two halves flip at the same time. How likely is that? It also depends on the hardware (suppose the buffer is two identical chips one over the other, skewered by the same cosmic ray incoming at a perfectly right angle...?).
Depending on the architecture, the compiler and optimizations used, either solution might turn out to be faster; probably not by all that much.

Related

C - How to initialize a memory space to 0x00, before allocating it to an array

I am trying to make an ssd1306 library for learning stm32, for which I've made an *init[] array. All of the defines and macros return uint8_t. The idea behind this was that I'll detect where NULL is in the memory and stop incrementing (the logical bug would be that this would fail if there were exactly 4,8,12,16... array elements in the rows, which is never the case). In this, I assumed that all the memory addresses allocated to the array would be initialized to 0x00 (obviously not), and I ran into a problem where a single random byte would corrupt everything. So, I was looking for a way to make all the memory locations 0x00. Feel free to suggest any new ways I could do the same thing.
I could declare *init[], do calloc, and then initialize every sub-array individually, but that would make adding new init parameters that much more cumbersome. If all else fails, ill use it.
uint8_t *init[]= {
(uint8_t[]){MUX_RATIO_ADDR, SET_MUX_RATIO(0X1F)},
(uint8_t[]){DISPLAY_OFFSET_ADDR, SET_DISPLAY_OFFSET(0X00)},
(uint8_t[]){DISPLAY_START_LINE(0)},
(uint8_t[]){SEG_REMAP(0x00)},
(uint8_t[]){SCAN_DIRECTION(0X00)},
(uint8_t[]){COM_CONFIG_ADDR, COM_CONFIG(0X01)},
(uint8_t[]){CONTRAST_CONTROL_ADDR, SET_CONTRAST(0X7F)},
(uint8_t[]){VER_ADDR_MODE},
(uint8_t[]){0X21, 0X3F, 0X7F},
(uint8_t[]){0X22, 0X4, 0X7},
(uint8_t[]){DISPLAY_ON(0)},
(uint8_t[]){INVERSE_MODE(0)},
(uint8_t[]){DISPLAY_CLK_DIVIDE_ADDR, DISPLAY_CLK_DIVIDE(1,8)},
(uint8_t[]){0xdb, 0x40},
(uint8_t[]){CHARGE_PUMP_ADDR, CHARG_PUMP_ON},
(uint8_t[]){NORMAL_MODE(1)}
};
for (int i=0; i<sizeof(init)/sizeof(init[0]); i++) {
for(int j=0; init[i][j] != '\0'; j++) {
HAL_I2C_Mem_Write(&hi2c1, DEV_ADDR, COMMAND_MODE, 1, &init[i][j], 1, 50);
}
}
HAL function declaration for referance:
HAL_StatusTypeDef HAL_I2C_Mem_Write (I2C_HandleTypeDef*, uint16_t , uint16_t , uint16_t, uint8_t*, uint16_t , uint32_t );
I'll detect where NULL is in the memory
What NULL? NULL is a macro for null pointer constants. Most likely with the value 0, but there are no null pointers anywhere in your code. No null terminated strings either.
In this, I assumed that all the memory addresses allocated to the array would be initialized to 0x00 (obviously not)
In the code you posted, everything is data and initialized to the values you have provided. You have intentionally made it as compact as possible. For example (uint8_t[]){0xdb, 0x40} means "allocate 2 bytes and fill them with this data". There is no null termination like in strings, because these are 8 bit integers, not strings, plus you didn't allocate any room for one either. You only get implicit null termination when you initialize with string literals: "like this".
Anyway, the whole code is nonsensical for a microcontroller program. This is a constant table, it should be const all over so that it ends up in flash, not in RAM. It's a huge waste of RAM memory. Compound literals (uint8_t[]) { ... } also get allocated in RAM. Don't use them in an embedded system unless you know what they actually do.
The best fix to salvage this code is probably to do this:
static const uint8_t init[][4]=
{
{MUX_RATIO_ADDR, SET_MUX_RATIO(0X1F)},
{DISPLAY_OFFSET_ADDR, SET_DISPLAY_OFFSET(0X00)}
...
};
Now the code is in flash and there's explicitly at least one zero at the end of each 1D array, because they are at most 3 bytes long. Array initialization is guaranteed to fill up spare bytes that weren't set with zeroes.
I wonder, if just a single array would be ok. This way, you would also save all the uint8_t pointers, you just need an additional byte instead.
static const uint8_t ssd1306_init[] = {
// len, data
2, MUX_RATIO_ADDR, SET_MUX_RATIO(0X1F),
2, DISPLAY_OFFSET_ADDR, SET_DISPLAY_OFFSET(0X00),
1, DISPLAY_START_LINE(0),
1, SEG_REMAP(0x00),
1, SCAN_DIRECTION(0X00),
2, COM_CONFIG_ADDR, COM_CONFIG(0X01),
2, CONTRAST_CONTROL_ADDR, SET_CONTRAST(0X7F),
1, VER_ADDR_MODE,
3, 0X21, 0X3F, 0X7F,
3, 0X22, 0X4, 0X7,
1, DISPLAY_ON(0),
1, INVERSE_MODE(0),
2, DISPLAY_CLK_DIVIDE_ADDR, DISPLAY_CLK_DIVIDE(1,8),
2, 0xdb, 0x40,
2, CHARGE_PUMP_ADDR, CHARG_PUMP_ON,
1, NORMAL_MODE(1),
};
for (int i = 0; i < sizeof(init)/sizeof(init[0]); i++)
{
for (int j = 0; j < init[i]; j++)
{
HAL_I2C_Mem_Write(&hi2c1, DEV_ADDR, COMMAND_MODE, 1, &init[i+1+j], 1, 50);
}
i += j; // advance i by number bytes transmitted
}
On the other side, when I look at your I2C Write function, it looks like you write one byte at a time anyway, no matter if a CMD, a ADDR/DATA pair or just a value triple. Why then the split into arrays and check for '\0' at all? If it works (*), my example would not even need the additional 1st byte for length. Just write the commands in an array of bytes, and send the array out:
static const uint8_t ssd1306_init[] = {
MUX_RATIO_ADDR, SET_MUX_RATIO(0X1F),
DISPLAY_OFFSET_ADDR, SET_DISPLAY_OFFSET(0X00),
...
}
for (int i = 0; i < sizeof(init)/sizeof(init[0]); i++)
{
HAL_I2C_Mem_Write(&hi2c1, DEV_ADDR, COMMAND_MODE, 1, &init[i], 1, 50);
}
(*) This "if it works" is about, if the device accepts it this way. I also wonder, if the HAL function would accept a certain number of bytes and does a burst transfer or such.
In that case, you might even use a DMA driven transfer.
But for this, you should consult the device and the HAL documentation more closely.

Run length encoding on binary files in C

I wrote this function that performs a slightly modified variation of run-length encoding on text files in C.
I'm trying to generalize it to binary files but I have no experience working with them. I understand that, while I can compare bytes of binary data much the same way I can compare chars from a text file, I am not sure how to go about printing the number of occurrences of a byte to the compressed version like I do in the code below.
A note on the type of RLE I'm using: bytes that occur more than once in a row are duplicated to signal the next-to-come number is in fact the number of occurrences vs just a number following the character in the file. For occurrences longer than one digit, they are broken down into runs that are 9 occurrences long.
For example, aaaaaaaaaaabccccc becomes aa9aa2bcc5.
Here's my code:
char* encode(char* str)
{
char* ret = calloc(2 * strlen(str) + 1, 1);
size_t retIdx = 0, inIdx = 0;
while (str[inIdx]) {
size_t count = 1;
size_t contIdx = inIdx;
while (str[inIdx] == str[++contIdx]) {
count++;
}
size_t tmpCount = count;
// break down counts with 2 or more digits into counts ≤ 9
while (tmpCount > 9) {
tmpCount -= 9;
ret[retIdx++] = str[inIdx];
ret[retIdx++] = str[inIdx];
ret[retIdx++] = '9';
}
char tmp[2];
ret[retIdx++] = str[inIdx];
if (tmpCount > 1) {
// repeat character (this tells the decompressor that the next digit
// is in fact the # of consecutive occurrences of this char)
ret[retIdx++] = str[inIdx];
// convert single-digit count to string
snprintf(tmp, 2, "%ld", tmpCount);
ret[retIdx++] = tmp[0];
}
inIdx += count;
}
return ret;
}
What changes are in order to adapt this to a binary stream? The first problem I see is with the snprintf call since it's operating using a text format. Something that rings a bell is also the way I'm handling the multiple-digit occurrence runs. We're not working in base 10 anymore so that has to change, I'm just unsure how having almost never worked with binary data.
A few ideas that can be useful to you:
one simple method to generalize RLE to binary data is to use a bit-based compression. For example the bit sequence 00000000011111100111 can be translated to the sequence 0 9623. Since the binary alphabet is composed by only two symbols, you need to only store the first bit value (this can be as simple as storing it in the very first bit) and then the number of the contiguous equal values. Arbitrarily large integers can be stored in a binary format using Elias gamma coding. Extra padding can be added to fit the entire sequence nicely into an integer number of bytes. So using this method, the above sequence can be encoded like this:
00000000011111100111 -> 0 0001001 00110 010 011
^ ^ ^ ^ ^
first bit 9 6 2 3
If you want to keep it byte based, one idea is to consider all the even bytes frequencies (interpreted as an unsigned char) and all the odd bytes the values. If one byte occur more than 255 times, than you can just repeat it. This can be very inefficient, though, but it is definitively simple to implement, and it might be good enough if you can make some assumptions on the input.
Also, you can consider moving out from RLE and implement Huffman's coding or other sophisticated algorithms (e.g. LZW).
Implementation wise, i think tucuxi already gave you some hints.
You only have to address 2 problems:
you cannot use any str-related functions, because C strings do not deal well with '\0'. So for example, strlen will return the index of the 1st 0x0 byte in a string. The length of the input must be passed in as an additional parameter: char *encode(char *start, size_t length)
your output cannot have an implicit length of strlen(ret), because there may be extra 0-bytes sprinkled about in the output. You again need an extra parameter: size_t encode(char *start, size_t length, char *output) (this version would require the output buffer to be reserved externally, with a size of at least length*2, and return the length of the encoded string)
The rest of the code, assuming it was working before, should continue to work correctly now. If you want to go beyond base-10, and for instance use base-256 for greater compression, you would only need to change the constant in the break-things-up loop (from 9 to 255), and replace the snprintf as follows:
// before
snprintf(tmp, 2, "%ld", tmpCount);
ret[retIdx++] = tmp[0];
// after: much easier
ret[retIdx++] = tmpCount;

Can I avoid a loop for writing the same value in a continous subset of an array?

I have a program where I repeat a succession of methods to reproduce time evolution. One of the things I have to do is to write the same value for a long continue subset of elements of a very large array. Knowing which elements are and which value I want, is there any other way rather than doing a loop for setting these values each by each?
EDIT: To be clear, I want to avoid this:
double arr[10000000];
int i;
for (i=0; i<100000; ++i)
arr[i] = 1;
by just one single call if it is possible. Can you assign to a part of an array the values from another array of the same size? Maybe I could have in memory a second array arr2[1000000] with all elements 1 and then do something like copying the memory of arr2 to the first 100.000 elements of arr?
I have a somewhat tongue-in-cheek and non-portable possibility for you to consider. If you tailored your buffer to a size that is a power of 2, you could seed the buffer with a single double, then use memcpy to copy successively larger chunks of the buffer until the buffer is full.
So first you copy the first 8 bytes over the next 8 bytes...(so now you have 2 doubles)
...then you copy the first 16 bytes over the next 16 bytes...(so now you have 4 doubles)
...then you copy the first 32 bytes over the next 32 bytes...(so now you have 8 doubles)
...and so on.
It's plain to see that we won't actually call memcpy all that many times, and if the implementation of memcpy is sufficiently faster than a simple loop we'll see a benefit.
Try building and running this and tell me how it performs on your machine. It's a very scrappy proof of concept...
#include <string.h>
#include <time.h>
#include <stdio.h>
void loop_buffer_init(double* buffer, int buflen, double val)
{
for (int i = 0; i < buflen; i++)
{
buffer[i] = val;
}
}
void memcpy_buffer_init(double* buffer, int buflen, double val)
{
buffer[0] = val;
int half_buf_size = buflen * sizeof(double) / 2;
for (int i = sizeof(double); i <= half_buf_size; i += i)
{
memcpy((unsigned char *)buffer + i, buffer, i);
}
}
void check_success(double* buffer, int buflen, double expected_val)
{
for (int i = 0; i < buflen; i++)
{
if (buffer[i] != expected_val)
{
printf("But your whacky loop failed horribly.\n");
break;
}
}
}
int main()
{
const int TEST_REPS = 500;
const int BUFFER_SIZE = 16777216;
static double buffer[BUFFER_SIZE]; // 2**24 doubles, 128MB
time_t start_time;
time(&start_time);
printf("Normal loop starting...\n");
for (int reps = 0; reps < TEST_REPS; reps++)
{
loop_buffer_init(buffer, BUFFER_SIZE, 1.0);
}
time_t end_time;
time(&end_time);
printf("Normal loop finishing after %.f seconds\n",
difftime(end_time, start_time));
time(&start_time);
printf("Whacky loop starting...\n");
for (int reps = 0; reps < TEST_REPS; reps++)
{
memcpy_buffer_init(buffer, BUFFER_SIZE, 2.5);
}
time(&end_time);
printf("Whacky loop finishing after %.f seconds\n",
difftime(end_time, start_time));
check_success(buffer, BUFFER_SIZE, 2.5);
}
On my machine, the results were:
Normal loop starting...
Normal loop finishing after 21 seconds
Whacky loop starting...
Whacky loop finishing after 9 seconds
To work with a buffer that was less than a perfect power of 2 in size, just go as far as you can with the increasing powers of 2 and then fill out the remainder in one final memcpy.
(Edit: before anyone mentions it, of course this is pointless with a static double (might as well initialize it at compile time) but it'll work just as well with a nice fresh stretch of memory requested at runtime.)
It looks like this solution is very sensitive to your cache size or other hardware optimizations. On my old (circa 2009) laptop the memcpy solution is as slow or slower than the simple loop, until the buffer size drops below 1MB. Below 1MB or so the memcpy solution returns to being twice as fast.
I have a program where I repeat a succession of methods to reproduce
time evolution. One of the things I have to do is to write the same
value for a long continue subset of elements of a very large array.
Knowing which elements are and which value I want, is there any other
way rather than doing a loop for setting these values each by each?
In principle, you can initialize an array however you like without using a loop. If that array has static duration then that initialization might in fact be extremely efficient, as the initial value is stored in the executable image in one way or another.
Otherwise, you have a few options:
if the array elements are of a character type then you can use memset(). Very likely this involves a loop internally, but you won't have one literally in your own code.
if the representation of the value you want to set has all bytes equal, such as is the case for typical representations of 0 in any arithmetic type , then memset() is again a possibility.
as you suggested, if you have another array with suitable contents then you can copy some or all of it into the target array. For this you would use memcpy(), unless there is a chance that the source and destination could overlap, in which case you would want memmove().
more generally, you may be able to read in the data from some external source, such as a file (e.g. via fread()). Don't count on any I/O-based solution to be performant, however.
you can write an analog of memset() that is specific to the data type of the array. Such a function would likely need to use a loop of some form internally, but you could avoid such a loop in the caller.
you can write a macro that expands to the needed loop. This can be type-generic, so you don't need different versions for different data types. It uses a loop, but the loop would not appear literally in your source code at the point of use.
If you know in advance how many elements you want to set, then in principle, you could write that many assignment statements without looping. But I cannot imagine why you would want so badly to avoid looping that you would resort to this for a large number of elements.
All of those except the last actually do loop, however -- they just avoid cluttering your code with a loop construct at the point where you want to set the array elements. Some of them may also be clearer and more immediately understandable to human readers.

Best approach to continuously scan for a string in a streaming buffer

I have this situation where my function continuously receive data of various length. The data can be anything. I want to find the best way I to hunt for particular string in this data. The solution will require somehow to buffer previous data but I cannot wrap my head around the problem.
Here is an example of the problem:
DATA IN -> [\x00\x00\x01\x23B][][LABLABLABLABLA\x01TO][KEN][BLA\x01]...
if every [...] represents a data chunk and [] represents a data chunk with no items, what is the best way to scan for the string TOKEN?
UPDATE:
I realised the question is a bit more complex. the [] are not separators. I just use them to describe the structure of the chunk per above example. Also TOKEN is not a static string per-se. It is variable length. I think the best way to read line by line but than the question is how to read a streaming buffer of variable length into lines.
The simplest way to search for TOKEN is:
try to match "TOKEN" starting from position 0 in the stream
try to match "TOKEN" starting from position 1 in the stream
etc
So all you need to buffer is a number of bytes from the stream equal to the length of "TOKEN" (5 bytes, or actually 4 will do). At each position try to match "TOKEN", which might require waiting until you have at least 5 bytes read into your buffer. If the match fails, rewind to where you started matching, plus one. Since you never rewind more than the length of the string you're searching for (minus one) that's all the buffer you really need.
The technical issue then is, how to maintain your 5 bytes of buffered data as you read continuously from the stream. One way is a so-called "circular buffer". Another way, especially if the token is small, is to use a larger buffer and whenever you get too near the end, copy the bytes you need to the beginning and start again.
If your function is a callback, called once for each new chunk of data, then you will need to maintain some state from one call to the next to allow for a match that spans two chunks. If you're lucky then your callback API includes a "user data pointer", and you can set that to point to whatever struct you like that includes the buffer. If not, you'll need global or thread-local variables.
If the stream has a high data rate then you might want to think about speeding things up, with the KMP algorithm or otherwise.
Sorry, I voted to delete my previous answer as my understanding of the question was not correct. I didn't read carefully enouogh and thought that the [] are token delimiters.
For your problem I'd recommend building a small state machine based on a simple counter:
For every character you do something like the following pseudo code:
if (received_character == token[pos]) {
++pos;
if (pos >= token_length) {
token_received = 1;
}
}
else {
pos = 0; // Startover
}
This takes a minimum of processor cycles and also a minimum of memory aso you don't need to buffer anything except the chunk just received.
If the needle is contained within memory, it could be assumed that you can allocate an equally-sized object to read into (e.g. char input_array[needle_size];).
To start the search process, fill that object with bytes from your file (e.g. size_t sz = fread(input_array, 1, input_size, input_file);) and attempt a match (e.g. if (sz == needle_size && memcmp(input_array, needle, needle_size) == 0) { /* matched */ }.
If the match fails or you want to continue searching after a successful match, advance the position forward by one byte (e.g. memmove(input_array, input_array + 1, input_size - 1); input_array[input_size - 1] = fgetc(input_file); and try again.
A concern was raised that this idea copies too many bytes around, in the comments. While I don't believe that this concern has a significant merit (as there is no evidence of significant value), the copies can be avoided by using a circular array; we insert new characters at pos % needle_size and compare the regions before and after that boundary as though they are the tail and head respectively. For example:
void find_match(FILE *input_file, char const *needle, size_t needle_size) {
char input_array[needle_size];
size_t sz = fread(input_array, 1, needle_size, input_file);
if (sz != needle_size) {
// No matches possible
return;
}
setvbuf(input_file, NULL, _IOFBF, BUFSIZ);
unsigned long long pos = 0;
for (;;) {
size_t cursor = pos % needle_size;
int tail_compare = memcmp(input_array, needle + needle_size - cursor, cursor),
head_compare = memcmp(input_array + cursor, needle, needle_size - cursor);
if (head_compare == 0 && tail_compare == 0) {
printf("Match found at offset %llu\n", pos);
}
int c = fgetc(input_file);
if (c == EOF) {
break;
}
input_array[cursor] = c;
pos++;
}
}

When sending an array of int over TCP, why are only the first amount correct?

Following my previous question (Why do I get weird results when reading an array of integers from a TCP socket?), I have come up with the following code, which seems to work, sort of. The code sample works well with a small number of array elements, but once it becomes large, the data is corrupt toward the end.
This is the code to send the array of int over TCP:
#define ARRAY_LEN 262144
long *sourceArrayPointer = getSourceArray();
long sourceArray[ARRAY_LEN];
for (int i = 0; i < ARRAY_LEN; i++)
{
sourceArray[i] = sourceArrayPointer[i];
}
int result = send(clientSocketFD, sourceArray, sizeof(long) * ARRAY_LEN);
And this is the code to receive the array of int:
#define ARRAY_LEN 262144
long targetArray[ARRAY_LEN];
int result = read(socketFD, targetArray, sizeof(long) * ARRAY_LEN);
The first few numbers are fine, but further down the array the numbers start going completely different. At the end, when the numbers should look like this:
0
0
0
0
0
0
0
0
0
0
But they actually come out as this?
4310701
0
-12288
32767
-1
-1
10
0
-12288
32767
Is this because I'm using the wrong send/recieve size?
The call to read(..., len) doesn't read len bytes from the socket, it reads a maximum of len bytes. Your array is rather big and it will be split over many TCP/IP packets, so your call to read probably returns just a part of the array while the rest is still "in transit". read() returns how many bytes it received, so you should call it again until you received everything you want. You could do something like this:
long targetArray[ARRAY_LEN];
char *buffer = (char*)targetArray;
size_t remaining = sizeof(long) * ARRAY_LEN;
while (remaining) {
ssize_t recvd = read(socketFD, buffer, remaining);
// TODO: check for read errors etc here...
remaining -= recvd;
buffer += recvd;
}
Is the following ok?
for (int i = 0; sourceArrayPointer < i; i++)
You are comparing apples and oranges (read pointers and integers). This loop doesnot get executed since the pointer to array of longs is > 0 (most always). So, in the receiving end, you are reading off of from an unitialized array which results in those incorrect numbers being passed around).
It'd rather be:
for (int i = 0; i < ARRAY_LEN; i++)
Use functions from <net/hton.h>
http://en.wikipedia.org/wiki/Endianness#Endianness_in_networking
Not related to this question, but you also need to take care of endianness of platforms if you want to use TCP over different platforms.
It is much simpler to use some networking library like curl or ACE, if that is an option (additionally you learn a lot more at higher level like design patterns).
There is nothing to guarantee how TCP will packet up the data you send to a stream - it only guarantees that it will end up in the correct order at the application level. So you need to check the value of result, and keep on reading until you have read the right number of bytes. Otherwise you won't have read the whole of the data. You're making this more difficult for yourself using a long array rather than a byte array - the data may be send in any number of chunks, which may not be aligned to long boundaries.
I see a number of problem's here. First, this is how I would rewrite your send code as I understand it. I assume getSourceArray always returns a valid pointer to a static or malloced buffer of size ARRAY_LEN. I'm also assuming you don't need sourceArrayPointer later in the code.
#define ARRAY_LEN 262144
long *sourceArrayPointer = getSourceArray();
long sourceArray[ARRAY_LEN];
long *sourceArrayIdx = sourceArray;
for (; sourceArrayIdx < sourceArray+ARRAY_LEN ; )
sourceArrayIdx++ = sourceArrayPointer++;
int result = send(clientSocketFD, sourceArray, sizeof(long) * ARRAY_LEN);
if (result < sizeof(long) * ARRAY_LEN)
printf("send returned %d\n", result);
Looking at your original code I'm guessing that your for loop was messed up and never executing resulting in you sending whatever random junk happens to be in the memory sourceArray points to. Basically your condition
sourceArrayPointer < i;
is pretty much guaranteed to fail the first time through.

Resources