Socket checksum issue - c

This may be a straightforward solution but basically I am sending a binary file piece-by-piece to another program using TCP and checking to make sure the checksum matches for validity. The problem is the checksum received is never the checksum sent apart from the last part submitted (the remainder).
The code fragment for the sender is:
void* buffer = (void *)malloc(BLOCKSIZE+1);
if (!buffer)
error("Error: malloc error for buffer.\n");
fread(buffer, BLOCKSIZE, 1, fp_read); //read from binary file for the current block.
int checksum = checksum(buffer,BLOCKSIZE);
n = write(sockfd,buffer,BLOCKSIZE);
if (n < 0)
error("ERROR writing to socket");
For the receiver is is:
void* buffer = (void *)malloc(BLOCKSIZE+1);
if (!buffer)
error("Error: malloc error for buffer.\n");
n = read(sockfd,buffer,BLOCKSIZE);
if (n < 0)
error("Error: reading from socket.");
int checksum = checksumv(buffer,BLOCKSIZE);
Anyone see anything wrong with it? The only part having checksums match is the final piece which doesn't completely fill the buffer.
Thanks.
The whole code for the sender is:
FILE* fp_read = fopen("file.jpg", "rb");
if (fp_read == NULL)
error("Cannot open the file for peer piece download.");
fseek(fp_read, 0, SEEK_END);
unsigned long fileLen = ftell(fp_read);
fseek(fp_read, 0, SEEK_SET);
int checksum, loops = fileLen / BLOCKSIZE;
int remainder = fileLen % BLOCKSIZE;
int segment_num = loops+1;
void* buffer4 = (void *)malloc(BLOCKSIZE+1);
if (!buffer4)
error("Error: malloc error for buffer.\n");
int i, sent = 0;
for (i=1; i<=loops; i++)
{
fread(buffer4, BLOCKSIZE, 1, fp_read);
checksum = checksumv(buffer4,BLOCKSIZE);
n = write(sock,buffer4,BLOCKSIZE);
if (n < 0)
error("ERROR writing to socket");
}
if (remainder > 0)
{
//Allocate memory
void* buffer5 = (void *)malloc(remainder+1);
if (!buffer5)
error("Error: malloc error for buffer2.\n");
fread(buffer5, remainder, 1, fp_read);
checksum = checksumv(buffer5,remainder);
n = write(sock,buffer5,remainder);
if (n < 0)
error("ERROR writing to socket");
}

When you are reading data:
n = read(sockfd,buffer,BLOCKSIZE);
if (n < 0)
error("Error: reading from socket.");
int checksum = checksumv(buffer,BLOCKSIZE);
you need to respect the number of bytes that read() says it placed into buffer - it may read fewer than BLOCKSIZE number of bytes before returning.
Also, I don't see where the checksum is sent (or received) - I only see the file data being sent. How are you comparing checksums?
Finally, since TCP is a streaming protocol, you'll need to have some way to indicate to receiver when the file data is finished such as by sending the size ahead of the file data, or having some 'out of band' indication.

You're not accumulating your checksum correctly, but you don't need all this complexity just to copy a file:
byte buffer[8192];
while ((count = fread(buffer, sizeof buffer, 1, fp)) > 0)
{
n = write(sock,buffer4,count);
if (n < 0)
error("ERROR writing to socket");
checksum += checksumv(buffer, count); // or possibly ^=, it depends how your checksum is supposed to accumulate
}

Related

Reading a file from a specific point problem

I'm using TCP server/client C application to send a file from server to client. File must be sent in parts (one part per one connection). I successfully send file from server to client, that's not the problem. The problem is with the one part per connection, getting the right part to be sent. I'm using fseek() to find the size of whole file and divided it by 4. That's the size of chunk that I want to be sent to client. A problem persists because I get more chunk than I actually expect.
// Retrieve file size
fSize = fileSize(filePtr);
// How much bytes to send
if (fSize >= 4)
{
leftToSend = fSize / SEND_DENOM;
}
else
{
leftToSend = fSize;
}
int fpOffset = leftToSend * (partToSend - 1);
fseek(filePtr, fpOffset, SEEK_SET);
int i = 0;
char cFromFile;
while(leftToSend != 0 || feof(filePtr))
{
cFromFile = fgetc(filePtr);
dataBuffer[i++] = cFromFile;
leftToSend--;
bytesSent++;
if (strlen(dataBuffer) == (BUFFER_SIZE - 1) || leftToSend == 0)
{
// Send message to client
iResult = sendto(clientSocket,
dataBuffer,
strlen(dataBuffer),
0,
(SOCKADDR *)&clientAddress,
sizeof(clientAddress));
if (iResult == SOCKET_ERROR)
{
printf("sendto failed with error: %d\n", WSAGetLastError());
closesocket(clientSocket);
WSACleanup();
ExitThread(100);
}
// Set whole buffer to zero
memset(dataBuffer, 0, BUFFER_SIZE);
i = 0;
}
}
Find file size function:
unsigned long long int fileSize (FILE* filePtr)
{
unsigned long long int fSize = 0;
fseek(filePtr, 0, SEEK_END);
fSize = ftell(filePtr);
rewind(filePtr);
return fSize;
}
Example (How it should look):
This is a problem...
chunk - This_
chunk - is_a_
chunk - probl
chunk - em...
And this is something I get:
chunk - This_is_a
chunk - is_a_prob
chunk - problem..
chunk - em...
where _ represents blank space
From the comments you've mentioned, try the following code.
I'll assume you calculate the leftToSend variable correctly.
while((leftToSend >= 0) || feof(filePtr))
{
cFromFile = fgetc(filePtr);
dataBuffer[i] = cFromFile;
i++;
leftToSend--;
if ((i >= (BUFFER_SIZE - 1)) || (0 == leftToSend) || (i >= (SEND_DENOM + 1)))
{
// Send message to client
iResult = sendto(clientSocket,
dataBuffer,
i,
0,
(SOCKADDR *)&clientAddress,
sizeof(clientAddress));
if (SOCKET_ERROR == iResult)
{
printf("sendto failed with error: %d\n", WSAGetLastError());
closesocket(clientSocket);
WSACleanup();
ExitThread(100);
}
// Set whole buffer to zero
memset(dataBuffer, 0, BUFFER_SIZE);
bytesSent += i;
i = 0;
}
}

Read the characters of an executable for file transfers in C

So recently for a course project, I decided to make myself a program that could transfer a file across a lan network and integrate it into the linux operating system (In this case, all I did was add it to the context menu) using a socket server.
The way it works is essentially,
Server is waiting.
Client connects.
Client sends a message of 1024 length with the first 4 characters reserved
The first 4 characters are used to store an int which will state the length of the message
server recieves them, writes them, then waits for the next block
when the server recieves a message where the length is 0
it ends the transfer and closes the files
This works for text files flawlessly. With improvements on my last code thanks to helpful feedback, I've managed to create something where the OS actually recognizes the file extension, regardless of the type. However for things like pngs they show up black, for exe's they immediately segfault.
What can I change in my reading and writing to get this to work regardless of file type? I'm not sure where to go, as what I have should work
Additional info: I am coding in C. To open the file I use fopen, fgetc and fputc.
Here is an exert from my code for my sever:
while (1){
n = read(newsockfd,message,1024);
if (n < 0) {
fclose(fptr2);
error("ERROR reading from socket");
}
//The first 4 bytes/characters are used to store the length.
//I read them by getting a pointer to the first char and then reading it as
//an int by casting it. This works with no problem
char *p=&message;
int *p2=(int*)p;
int length=*p2;
//Checks if the length is 0, if so, exit
if (length==0)
break;
//writes to the file
for (int i=4;i<length;i++){
fputc(message[i], fptr2);
}
n = write(newsockfd,"Ready",5);
if (n < 0)
error("ERROR writing to socket");
bzero(message,255);
}
fclose(fptr2);
//n = write(newsockfd,"I got your message",18);
//if (n < 0) error("ERROR writing to socket");
printf("Done.\n");
return 0;
}
Exert from my client, which reads the file in and then sends it.
while (finished!=0&&c!=EOF)
{
for (int i =4;i<1024;i++)
{
if (c==EOF)
{
char* p=&message;
int* pi=(int*)p;
*pi=i;
finished=0;
//printf("length is:%d\n",i);
break;
}
//printf("%c",c);
message[i]=c;
//fputc(c, fptr2);
c = fgetc(fptr1);
}
if (finished!=0)
{
char* p=&message;
int* pi=(int*)p;
*pi=1024;
}
n = write(sockfd,message,1024);
if (n < 0)
{
fclose(fptr1);
error("ERROR writing to socket");
}
bzero(message,1024);
//reading
n = read(sockfd,buffer,255);
if (n < 0)
error("ERROR reading from socket");
}
0x00 is a valid character for a binary file, so you can't "stop" when you see one [like you can for a string].
You are using the first char of a packet as an EOF marker (i.e. non-zero means valid data and zero means EOF). But, note that the first data char in a packet could be zero, so you have to use a one byte "header" that doesn't have data chars in it, merely the "stop" flag char [if you will]:
while (1) {
// Reading
n = read(newsockfd, message, 1023);
if (n < 0) {
fclose(fptr2);
error("ERROR reading from socket");
}
// Checks if the first character is null, if so, exit
if (message[0] == 0)
break;
// writes to the file
// NOTE: now the data starts at offset 1!
int i = 1;
for (; i < n; ++i) {
fputc(message[i], fptr2);
}
i = 0;
n = write(newsockfd, "Ready", 5);
if (n < 0)
error("ERROR writing to socket");
bzero(message, 1023);
}
fclose(fptr2);
But, a simpler way is to just read until the length comes back zero:
while (1) {
// Reading
n = read(newsockfd, message, 1024);
// end of data
if (n == 0)
break;
// error
if (n < 0) {
fclose(fptr2);
error("ERROR reading from socket");
}
// writes to the file
fwrite(message,1,n,fptr2);
i = 0;
n = write(newsockfd, "Ready", 5);
if (n < 0)
error("ERROR writing to socket");
bzero(message, 1023);
}
fclose(fptr2);
In short, the most important change to get this to work is changing when the program stops reading. EOF is simply -1, in a text file, this is no problem, however in other files this value can be found potentially anywhere. In order to read in the characters properly you must first get the file length, then simply read characters until you reach that.
fseek(fptr1, 0L, SEEK_END);
int sz = ftell(fptr1);
rewind(fptr1);
int count=0;
while (count!=sz)
{
//other code left out for simplicity
c = fgetc(fptr1);
count++;
}
With this change, my program works properly.

Socket programming sending and receiving messages with a loop in C

I just started learning socket programming and I'm trying to send and receive between the client and the server using TCP. First I am sending the client the size of the current directory from the server, and the client is receiving it perfectly fine. Then I want to send from the server each file name in the current directly so I created a loop to do so. In the client, I also have a loop for receiving all of the file names that executes as many times as there are files (the directory size). The problem is that when I print out what was received in the loop, the buffer is blank. I realized that the bytes received for the first loop is 55 and the rest are 0 but the buffer is always blank. Here are my code snippets:
Server:
if(strcmp(buffer, "ls-remote") == 0){ //display files from server directory
// get the size of the directory
unsigned long size = htonl(directorySize());
n = send(newsockfd, &size, sizeof(size), 0);
if(n < 0) syserr("can't send to server");
DIR *d = opendir(".");
struct dirent *dir;
if (d)
{
while((dir = readdir(d))!= NULL)
{ memset(&buffer[0], 0, sizeof(buffer)); // clear buffer
strcat(buffer, dir->d_name);
n = send(newsockfd, buffer, strlen(buffer), 0);
if(n < 0) syserr("can't send to server");
}
closedir(d);
}
else{
syserr("Error...could not get files from directory.");
}
}
Client:
if(strcmp(buffer, "ls-remote") == 0){ //display files from server directory
unsigned long size;
n = recv(sockfd, &size, sizeof(uint32_t), 0);// recieve the size of the directory
if(n < 0) syserr("can't receive from server");
size = ntohl(size);
while(size > 0){
memset(&buffer[0], 0, sizeof(buffer)); // clear buffer
n = recv(sockfd, buffer, 255, 0); // recieve directory from server
if(n < 0) syserr("can't send to server");
buffer[strlen(buffer) - 1] = '\0';
printf("recieving: %s\n", buffer); // print directory
size--;
}
}
One problem here is that there is no synchronization between the server sending the size of the directory and the directory entries and the client receiving them. In other words, if the directory contains entry.1, entry.2, and entry.3, the client may receive, for example, entry.1 and entry.2entry.3, or entry.1entry.2 and entry.3. This is true even if unicode is not involved here as a culprit, as suggested by JVene.
A couple other things:
buffer[strlen(buffer) - 1] = '\0'; in the client code will chop off
the last character. It should be buffer[strlen(buffer)] = '\0';
instead.
consistency in type usage with the sizeof() operator is important.
E.g., on my Mac sizeof(long) is 8, while sizeof(uint32_t) is 4.
This leads to even more interesting side-effects of the lack of
synchronization between the client and the server.
The "synchronization" issue here is due to the possibility that by the time the client gets around to reading from the socket, the server has already written several directory entries, so the client will read them all as one string. Things will get even messier if the directory size is written to and read from the socket assuming different buffer size; see above.
After some additional experimentation I have come up with code that seems to work. I'm sure there are improvements that could be made, there are other approaches, and there are scenarios the code doesn't account for, e.g. what if the directory is changing as the programs are running. This is just a proof of concept piece of code that will hopefully help you move in the right direction.
The idea here is for the server to write directory entries to the socket separated by NULL characters. These are then used as delimiters on the client side to tell dir entries apart. See comments in the code.
The server code writing dir entries to the socket:
// Assume maximum entry length is 255
// The buffer is 256 bytes long to accommodate the NULL-terminator.
// The terminator is important for the client as direntry delimiter.
char buffer[256];
// get the size of the directory
unsigned long size = htonl(dirSize());
int n = send(client_sock, &size, sizeof(size), 0);
if(n < 0) puts("can't send size to server");
DIR *d = opendir(".");
struct dirent *dir;
if (d)
{
while((dir = readdir(d))!= NULL)
{
memset(&buffer[0], 0, sizeof(buffer)); // clear buffer
strcat(buffer, dir->d_name);
// Write up to 255 chars of direntry + the NULL-terminator.
n = send(client_sock, buffer, strlen(buffer) + 1, 0);
if(n < 0) puts("can't send entry to server");
}
closedir(d);
}
else{
puts("Error...could not get files from directory.");
}
The client code that reads from the socket:
char buffer[256];
/*
* We need this in case the beginning of a directory entry is in one buffer, but
* the end is in the next.
*/
char buf_1[256];
unsigned long size;
buf_1[0] = 0; // make sure strlen(buf_1) is 0.
int n = recv(sockfd, &size, sizeof(long), 0);// recieve the size of the directory
if(n < 0) puts("can't receive size from server");
size = ntohl(size);
while(size > 0){
memset(&buffer[0], 0, sizeof(buffer)); // clear buffer
n = recv(sockfd, buffer, 255, 0); // keep last element of buffer as 0
if(n < 0) puts("can't receive entry from server");
int _start = 0;
if (strlen(buf_1)) // something left over from previously read buffer
{
// buf_1 contains beginning of an entry, buffer - the end
strcat(buf_1, buffer); // Assume there is a 0-terminator somewhere in buffer
printf("receiving: %s\n", buf_1); // buf_1 now has the entry, print it buf_1[0] = 0; // flag buf_1 as empty
size--; // we are one direntry down
_start += strlen(buffer) + 1; // move _start to char following 0-terminator
}
// Loop while _start is 0 - 254, the char at offset _start is not NULL,
// and there are still entries to retrieve.
while (_start < 255 && *(buffer + _start) && size > 0)
{
if (strlen( buffer + _start ) + _start >= 255) // no null terminator, need buf_1
{
strcpy(buf_1, buffer + _start); // copy unfinished entry to buf_1
// don't decrement size, we haven't extracted a full direntry.
break; // out of the inner while to read more from the socket.
}
else // we have a full direntry
{
printf("receiving: %s\n", buffer + _start); // print it
_start += strlen(buffer + _start) + 1; // move offset to next possible entry
size--; // one entry down
}
}
}
Hope this helps, good luck! Let me know if you have additional questions.

client can't read after connection with server in tcp

I wrote function for read and write for a tcp program . I output in server side but I can't get read on client side . my code
read function :
int read_data (int sd , char **data_buf)
{
int in_length,length,size,bytesread;
char *temp_buf;
size = read(sd,&in_length,sizeof(in_length));/*send entire length of data*/
if( 0 > size )
{
printf("Error on reading from socket\n");
exit(1);
}
length = ntohl(in_length);
printf("Total length coming : %d\n",length);
*data_buf =(char *)malloc((length+1)*sizeof(char));
temp_buf =(char *)malloc((length+1)*sizeof(char));
while(length> 0)
{
bytesread = read(sd,temp_buf,4);
strcat(*data_buf,temp_buf);
temp_buf = temp_buf + bytesread;
length = length - bytesread;
}
return 1;
}
and my write functions as :
int write_data (int sd , char *buffer)
{
int length,len_buff,bytesread,size;
len_buff = strlen(buffer);/*total length of string*/
printf("string == %s\n",buffer);
length = htonl(len_buff);/*convert to host to n/w*/
printf("Total length send =%d\n",len_buff);
size = write(sd,&length,sizeof(length));/*write total size to server */
if( 0 > size)
{
printf("error\n");
exit(0);
}
while(length > 0)
{
bytesread = write(sd,buffer,4);/*write 4 bytes to server*/
buffer = buffer + bytesread;
length = length - bytesread;
}
return 1;
}
client program :
///.............code for socket and connections.................//
ret = write_data(sd,user_string);/*write entire datas to server*/
value_from_server = read_data(sd,&data_buf);
server side program :
value_from_client = read_data(connfd,&data_buf);
printf("the value from client : %s\n",data_buf);
index = string_function(data_buf,&store_buf);
printf("after string process : %s\n",store_buf);
write_data(connfd,store_buf);
printf("i am waiting for next string\n");
connfd is the new socket for communication with client . reading and writing function work perfectly on server side . writing function work on client side . but reading from server not work in client program . ant mistake on my code ?
bytesread = read(sd,temp_buf,4);
Why read 4 bytes always inside the loop? You should be reading the remaining number of bytes to be read. The socket is blocking and hence will be stuck if the server is done sending but client still tries reading 4 bytes to arrive in the last iteration.
Have print statements inside the loop to know the bytes read in each iteration and see if client is blocked with read
Your code has several logic errors.
size = read(sd,&in_length,sizeof(in_length));/*send entire length of data*/
if( 0 > size )
{
printf("Error on reading from socket\n");
exit(1);
}
length = ntohl(in_length);
Here you are assuming you read four bytes, rather than fewer, or end of stream. You must check for end of stream (zero return value), and you must loop until you get the four bytes.
while(length> 0)
{
bytesread = read(sd,temp_buf,4);
strcat(*data_buf,temp_buf);
temp_buf = temp_buf + bytesread;
length = length - bytesread;
}
Here again you are ignoring the possibility of end of stream or an error. It should be:
while ((bytesread = read(sd,temp_buf, length)) > 0)
{
temp_buf += bytes_read;
length -= bytesread;
}
if (bytesread < 0)
{
perror("read 2");
}
else if (length > 0)
{
// end of stream before all expected bytes were received ...
}
else
{
// The OK case
}
Your sending code is suboptimal:
while(length > 0)
{
bytesread = write(sd,buffer,4);/*write 4 bytes to server*/
buffer = buffer + bytesread;
length = length - bytesread;
}
There's no point in chunking into 4-byte writes. It should be:
while (length > 0)
{
bytesread = write(sd, buffer, length);
buffer = buffer + bytesread;
length = length - bytesread;
}
and of course the misnamed bytesread variable should be called byteswritten. In fact you can rely on this loop only executing once. Again it should be followed by a test of byteswritten == -1 to check for errors.
Your functions have logic errors in them.
The reading loop is reading exactly 4 bytes on each iteration. If the length of the data being read is not an even multiple of 4, read() will block on the last iteration waiting for data that does not arrive. The reading loop is also assuming that read() returns a null-terminated buffer, but that is not the case, so strcat() will attempt to copy data from surrounding memory and will either copy garbage or crash with a segfault. Also, the reading function is not null-terminating the data buffer it returns to the caller, but the caller assumes it is null-terminated.
The writing loop is writing exactly 4 bytes on each iteration. If the length of the data is not an even multiple of 4, write() will attempt to write data from surrounding memory on the last iteration, and will either send garbage or crash with a segfault.
You are also not doing adequate error handling in either function.
Try something more like this instead:
void read_raw_bytes (int sd, void *data, int length)
{
int bytes_read;
char *data_ptr;
data_ptr = (char*) data;
while( length > 0 )
{
bytes_read = read(sd, data_ptr, length);
if( bytes_read < 0 )
{
printf("Error on reading from socket\n");
exit(1);
}
if( bytes_read == 0 )
{
printf("Disconnected while reading from socket\n");
exit(1);
}
data_ptr += bytes_read;
length -= bytes_read;
}
}
void write_raw_bytes (int sd, void *data, int length)
{
int bytes_sent;
char *data_ptr;
data_ptr = (char*) data;
while( length > 0 )
{
bytes_sent = write(sd, data_ptr, length);
if( bytes_sent < 0 )
{
printf("Error on writing to socket\n");
exit(0);
}
data_ptr += bytes_sent;
length -= bytes_sent;
}
}
int read_data (int sd, char **data_buf)
{
int length;
read_raw_bytes (sd, &length, sizeof(length)); /*send entire length of data*/
length = ntohl(length);
printf("Total length coming : %d\n", length);
*data_buf = (char *) malloc((length+1)*sizeof(char));
if (*data_buf == NULL)
{
printf("Error on allocating memory\n");
exit(1);
}
read_raw_bytes (sd, *data_buf, length);
(*data_buf)[length] = 0;
return 1;
}
int write_data (int sd, char *buffer)
{
int length, len_buff;
len_buff = strlen(buffer); /*total length of string*/
printf("string == %s\n", buffer);
printf("Total length send =%d\n", len_buff);
length = htonl(len_buff); /*convert to host to n/w*/
write_raw_bytes (sd, &length, sizeof(length)); /*write total size to server */
write_raw_bytes (sd, buffer, len_buff);
return 1;
}

Using read and write to do a server and a client (FTP protocol)

My code is too long to post all here so i'm going to sum up what's wrong.
In a server part i'm sending on a socket 3 things :
A message
The content of a file
Another message
In a client part i'm receiving these things but :
This first is to print on terminal
The second to write in a new file
The last to print on the terminal too
But my client is stuck on a read and i really don't know why. I'm on the problem for hour so if someone can help me, it will be very great !
edit : Basically, i think my problem is that i don't know what to write on the server to stop the read on the client.. Is it \n, \0.. ?
Here's the 2 part of code :
server
void send_content(t_server *s, FILE *fd, int rfd)
{
int len;
char *buff;
write(s->socket, "150 File status okay;" \
"about to open data connection.\n\0", strlen("150 File status okay;about to open data connection.\n\0"));
fseek(fd, 0, SEEK_END);
len = ftell(fd);
buff = malloc(len * sizeof(char));
read(rfd, buff, len);
write(s->socket, buff, len);
write(s->socket, "\n\0", strlen("\n\0"));
write(s->socket, "226 Closing data connection.\n\0", strlen("226 Closing data connection.\n\0"));
free(buff);
}
client
void getfile(t_client *c, char **tab)
{
int ret;
int fd;
int z;
char buff[4096];
z = 0;
read(c->fd, buff, 4096);
write(1, buff, strlen(buff));
if (strlen(buff) < 25)
return ;
fd = creat(tab[1], S_IRUSR | S_IWUSR);
while (z == 0 && (ret = read(c->fd, buff, 4096)) > 0)
{
if (ret < 4096)
z = -1;
write(fd, buff, strlen(buff));
memset(buff, '\0', 4096);
}
read(c->fd, buff, 4096); // Stuck here
write(1, buff, strlen(buff));
close(fd);
}
Like noted you need a read function like this to make sure you receive
specified number of bytes(this function will loop till it receives number of bytes it was told to). Just use this receivall method instead of read everywhere.
With files you typically first send the file length, and then receive the file.
I did something similar while ago, hope it will help you a bit. This is the client side, which tries to receive first file length from the server, then the file:
/* create file */
FILE * ptrMyFile = fopen(&filenames[i][0],"wb");
if(NULL == ptrMyFile)
{
printf("Unable to open file \n");
return 1;
}
int size = 0;
int t = 4;
/* first receive file size from server */
/* NOTE: error checking is omitted from code, nevertheless users should stil do some error checking when using this code */
readall(sockfd, (unsigned char*) &size, &t);
/* how many 256 byte chunks are there? */
int div = size / 256;
/* loop to receive each chunk. */
for(int k = 0; k < div; k++)
{
int chunk_size = 256;
/* make sure we receive 256 bytes */
readall(sockfd, buffer, &chunk_size);
/* write to file */
fwrite(buffer, chunk_size, 1, ptrMyFile);
}
/* read the final chunk. */
int whatsleft = size - 256 * div;
readall(sockfd, buffer, &whatsleft);
/* write */
fwrite(buffer, whatsleft, 1, ptrMyFile);
/* close file */
fclose(ptrMyFile);
I leave the server part to you.
char buff[4096];
z = 0;
read(c->fd, buff, 4096);
write(1, buff, strlen(buff));
You should be saving the return value of the call to read(), in order to find out how many bytes you just received. You may have to make several calls to read() in order to get the entire message. It's wrong to use strlen() to find out how many bytes were received, because the buffer contents are uninitialized, and the first chunk of the message could be cut off anywhere, so you can't count on it being null-terminated.

Resources