pirox22 pirox22 - 1 month ago 6
C Question

Sending huge array through socket

I am trying to send a char array of 100.000.000 bytes (maybe more) from a server to a client through a TCP socket in C.

I am doing this like that:

char *array; // global array malloc'd (SIZE)

//#######################
// server code
//#######################
int i;
int SIZE = 100000000

for (i = 0; i < SIZE; i = i + 4){
write(id, &array[i], 4); // write 4 bytes every time
}

//#######################
// client code
//#######################
int i;
int SIZE = 100.000.000
for (i = 0; i < SIZE; i = i + 4)
read(id, array + i, 4); // read 4 bytes


Problems:

1) When I try to send more bytes something goes wrong with the transfer. For example if I change 4 to 100, it says "broken pipe". Why does that happen?

2) I know this is not a "safe" way for reading/writing since I am not checking read() and write() return values. How can I do that?

3) Do I have to use htonl() and ntohl() functions?

Answer
 #include<stdlib.h>
 #include<stdio.h>
 #include<string.h>
 #include <sys/types.h>          
 #include <sys/socket.h>   

 //in @param
 //@param fd the socket file descriptor
 //@param array an array of data source to write to send to the connected client 
 //@param SIZE the size of data source to send to the client
 //@param sz_emit the size of data to send in one loop step
 //out @param
 //total length of data emited to the client

 int write_to_client(int fd, char* array, int SIZE, int sz_emit)
 {
   //#######################
   //    server code
   //#######################
   int i=0, sz=0;
   for(i = 0; i < SIZE; i += sz_emit )
   {  
       while(sz_emit-sz)
       { 
         sz+=write(id, array+i+sz, sz_emit-sz);
       }
       sz = 0;
   }
   return i;
 }

//#######################
//    client code
//#######################
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>          
#include <sys/socket.h>

//in @param
//@param fd is the file descriptor of the socket to read from
//@param SIZE the size of datas you want to read from the socket
//@param sz_received the size of byte to read in one loop step
//@param length, the length of data received
//@param read_err if 0 no error if -1 an error occurs use errno from #include <errno.h> to know more about that error 
//out @param
//a pointer to an array of size SIZE containing the data readed
char* receive_from_server(int fd, int SIZE, int sz_received, int* length, int* read_err)
{
  *read_err = 0;
  int i = 0, sz = 0, rt = 0, count=0;
  char *array = (char *)malloc(SIZE);
  memset(array, 0, SIZE);  
  for (i = 0; i < SIZE; i += sz_received)
    {
      while(sz_received-sz)
      { 
        rt = read(id, array + i + sz, sz_received-sz);
        if(rt==-1)
        {
          *read_err=rt;
          printf("an error occurs\n");
          goto l;
        }
        if(!rt)goto l;
        sz+=rt;
        count += sz;   
      }
      sz = 0;
    }
  l: *length = count;
  return array;
}

usage:

//server side
int SIZE = 100000000;
char array_to_send[SIZE]={'r'};
int sz_data_emited = write_to_client(sock, array_to_send, SIZE, 4);
printf("how many byte data emited:%d\n", sz_data_emited);

//client side
int SIZE = 100000000, length = 0, read_err=0;
char*array_received = NULL;
array_received = receive_from_server(sock, SIZE, 4, &length, &read_err);
if(!read_err)printf("get some datas\n");
// free array_received when finished...free(array_received)

some notes:

you need to pay attention on endianess when you want to transfert a multi-byte entity for example a short, int, long, utf-16 etc but if your datas are utf-8 or ascii text you don't need it.