Sending large file through sockets

Hello, I am trying to send a file (1 MB) through sockets and for some reason I am getting segmentation fault message and receiving in the server an incomplete file. The current file is about 3 pages long and need to send it from the client to the server. I've tried malloc with free(), I am now trying the read stream and write stream, with the fdopen and the flush at the end. I'm new with Linux and didnt know where to place my question.
I guess my question(s) are: how can I send the complete file to the server? Is there another function in c that I can use?
The global variables are declared elsewhere.
Thank you

Here is the code:

#include "sockheaders.h"

void bail(const char *on_what) {
if ( errno != 0 ) {
fputs(strerror(errno),stderr);
fputs(": ",stderr);
}
fputs(on_what,stderr);
fputc('\n',stderr);
exit(1);
}

int create_server_socket(char srvr_addr, char srvr_port){
/
srvr_addr = NULL;
srvr_port = "9099";
srvr_addr = "127.0.0.1";
/
/*Create a TDP/IP socket to use : */

s = socket\(PF\_INET,SOCK_STREAM,0\);
if \( s == -1 \)\{ bail\("socket\(\)"\);\}
        /* Create a server socket address:  */
memset\(&adr_srvr,0,sizeof adr_srvr\);
adr\_srvr.sin_family = AF_INET;
adr\_srvr.sin_port = htons\(atoi\(srvr_port\)\);
if \( strcmp\(srvr_addr,"*"\) != 0 \) \{
            /* Normal Address */
    adr\_srvr.sin\_addr.s_addr = inet\_addr\(srvr_addr\);
    if \( adr\_srvr.sin\_addr.s_addr == INADDR_NONE \)
        bail\("bad address."\); \} 
else \{ adr\_srvr.sin\_addr.s_addr = INADDR_ANY;\} /* Wild Address */

/*Bind the server address: */
len_inet = sizeof adr_srvr;
z = bind\(s,\(struct sockaddr *\)&adr\_srvr,len_inet\);
if \( z == -1 \) \{ bail\("bind\(2\)"\);\}
/* Make it a listening socket:  */
z = listen\(s,10\);
if \( z == -1 \) \{ bail\("listen\(2\)"\);\}
//FILE *rx;  /* read stream */
//FILE *tx;   /* write stream */
//s = socket\(PF\_INET,SOCK_STREAM,0\);

srx = fdopen\(s,"r"\);
if \( srx == NULL \) \{
fprintf\(stderr, "%s: fdopen\(s,'r'\)\\n",strerror\(errno\)\);
    exit\(1\);
\}
stx = fdopen\(dup\(s\),"w"\);
if \( stx == NULL \) \{
    fprintf\(stderr,"%s: fdopen\(s,'w'\)\\n",strerror\(errno\)\);
    exit\(1\);
\}
setlinebuf\(srx\); /* Line Buffered Mode */
setlinebuf\(stx\); /* Line Buffered Mode */

return 1;

}

send_server_message(){

    strcpy\(dtbuf,"<html><bold> I am the server!</bold></html>"\);

/*##################################################################/
/
-----------------connection section-------------------------------/
/*##################################################################
/

    /* Wait for a connect : */
    len_inet = sizeof adr_clnt;
    c = accept\(s,\(struct sockaddr *\)&adr\_clnt,&len_inet\);
    if \( c == -1 \)\{ printf\("problem with accept\\n"\);\}

/--------- recieve message----------/
recieved[0]=0;
z = read(c,&recieved,sizeof recieved -1);
if ( z == -1 ){ printf("cannot read from socket 001\0");}
printf("int is: %s\n",recieved);

/---------Write result back to the client---------/

printf\(" sending the following %s\\n",dtbuf\);
z = write\(c,&dtbuf,sizeof dtbuf\);//changed by coe
if \( z == -1 \)\{ printf\("unable to write to socket"\);\}
/*CLOSE CLIENT CONNECTION*/
    close\(c\);

return 1;

}

int create_client( char srvr_addr1, char srvr_port1){
/*##########################################################
/
/*--------------connection1-setup---------------------------
/
/*##########################################################*/
/*srvr_addr1 = NULL;
srvr_port1 = "9099";
srvr_addr1 = "127.0.0.1"; /
s1 = socket(PF_INET,SOCK_STREAM,0);
if ( s1 == -1 ){/*bail("socket()");
/}

        /*Create a server socket address: */
    memset\(&adr_srvr1,0,sizeof adr_srvr1\);
    adr\_srvr1.sin_family = AF_INET;
    adr\_srvr1.sin_port = htons\(atoi\(srvr_port1\)\);
    adr\_srvr1.sin\_addr.s_addr = inet\_addr\(srvr_addr1\);
if \( adr\_srvr1.sin\_addr.s_addr == INADDR_NONE \)\{/*bail\("bad address."\);*/\}

        /*Connect to the server: */
len_inet1 = sizeof adr_srvr1;

/create the connection/
z1 = connect(s1,&adr_srvr1,len_inet1);
if ( z1 == -1 ){ /*bail("connect(2)");*/}
//FILE rx; / read stream */
//FILE tx; / write stream */
//s = socket(PF_INET,SOCK_STREAM,0);

crx = fdopen\(s1,"r"\);
  
if \( crx == NULL \) \{
    fprintf\(stderr, "%s: fdopen\(s,'r'\)\\n",strerror\(errno\)\);
    exit\(1\);
\}
ctx = fdopen\(dup\(s1\),"w"\);
if \( ctx == NULL \) \{
    fprintf\(stderr,"%s: fdopen\(s,'w'\)\\n",strerror\(errno\)\);
    exit\(1\);
\}
setlinebuf\(crx\); /* Line Buffered Mode */
setlinebuf\(ctx\); /* Line Buffered Mode */

return 1;
}

int send_message(){

/*##########################################################/
/*--------------connection1-message-------------------------
/
/*##########################################################*/

strcpy(dtbuf,"I am the client!");
printf("sending: %s\n",dtbuf);

z1= send\_File\_To_Server\(\);
  if \( z1 == -1 \)\{ /\*bail\("write\(2\)"\);*/\}
  z1= read\(s1,&dtbuf,sizeof dtbuf -1\);

printf\("data recieved is %s",dtbuf\);
    close\(s1\);
    putchar\('\\n'\);

}

int send_File_To_Server(){

FILE *ptr;
ptr = fopen("config.c", "r"); //open file
crx = fdopen(c, "r");
if (!crx){
close(c);
//continue;
}
ctx = fdopen(dup(c), "w");
if (!ctx){
close(c);
//continue;
}

srx = fdopen(s1, "r");
if (!srx){
close(s1);
//continue;
}
stx = fdopen(dup(s1), "w");
if (!stx){
close(s1);
//continue;
}
setlinebuf(srx); /* Line Buffered Mode /
setlinebuf(stx); /
Line Buffered Mode */

int ch;
int Pos,Length;
Pos = ftell(ptr);
fseek(ptr, 0L, SEEK_END);
Length = ftell(ptr);
fseek(ptr,Pos, SEEK_SET);
char temp[1048576];

int i=0;
while ((ch = getc(ptr)) != EOF/*!feof(ptr)*/){
temp[i]=ch;
i++;
} //prints everything from the file into the console

fputs(temp, stx);//to the server
fflush(stx);

}

This is related to high level programming so I move your thread there. Also use CODE-tags in future when posting code, data or logs, ty.

Thank you for the correction.

here's my two cents: "you just have to do as if in a file copy program" ;

  • that's the whole idea behind sockets ... once a connection is established , it's just another good ol' file i/o thing !

  • the only detail you should bear in mind is that the default packet size is 1500 bytes, and it's no use reading(receiving) or writing(sending) chunks bigger than this ;

(remember : this is plain bread-and-butter default conditions - for newbies - and anything more complicated than this can be done with proper study)

finally, some sample code (for the client who sends the file):

int sockfd , count ;
char buf[1500] ;
/* plain connection */
sockfd = socket (AF_INET, ...) ;
connect (sockfd, ...) ;
/* now the good ol' plain file i/o */
while (filesize > 0) {
   count = send (sockfd, buf, 1500, 0) ;
   filesize -= count ;
}

good luck, and success !
alexandre botao
Alexandre V. R. Botao | Unix, C/C++, Shell, LDAP, SSL/TLS, SSH, Perl, Java, Python, Security, ...

Thank you very much!
I am going to try that, and since Its better to send 1500 bytes at a time, I'll do a loop to free up the buffer until the file its completely sent.

Thanks again

You mean, MTU is 1500 by default.
But how can we learn what's the actual MTU in that system?

There could even be several MTU's, for different interfaces going to different places. Unless your ISP has decided to block ICMP, its usually not worth worrying about too deeply.

Ummm, you left out the part about reading the file into the buffer.

That's why I like sendfile() - it's simpler. It's just open(), fstat() to get the file length, then sendfile().

SYNOPSIS
#include <sys/sendfile.h>

   ssize_t sendfile\(int out_fd, int in_fd, off_t *offset, size_t count\);

DESCRIPTION
Presently (Linux 2.6.9): in_fd, must correspond to a file which supports mmap(2)-like operations (i.e., it cannot be a socket); and out_fd must refer to a socket.