Thread: transfer binary over socket

  1. #1
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300

    transfer binary over socket

    I want to transfer a binary file over a socket.

    The file has been fread into a character buffer and can be successfully fwritten back out locally. Using write and read on the socket file descriptors seemed to work in the sense that a file of the correct size is transferred, but it's not executable (or viewable, with an image).

    If I want to use fread and fwrite, I have to use fdopen on the socket descriptor to get a stream. This works on the transmission end, but

    FILE sstrIN=fdopen(fd,"rb");

    fails, altho fcntl reports the read flag is set for fd. Am I going about this the wrong way, or are there more details?
    Last edited by MK27; 10-08-2008 at 11:17 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  2. #2
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    FILE sstrIN=fdopen(fd,"rb");
    FILE or FILE *?

  3. #3
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    What is errno after the failure?

    gg

  4. #4
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Codeplug View Post
    What is errno after the failure?
    Bad file descriptor


    However, the fd is working fine with "read" and write".

    I actually have been unable to repeat the situation where this works on the transmit end -- ie, apparently I cannot create a stream for a socket descriptor AT ALL.

    The other strange element is that it would seem to me (based on the reading I've done) that I shouldn't even have to -- simply writing the buffer in a single chunk on the socket should work fine (can anyone confirm this?). As I said, there is a transfer that creates a binary file of the correct size, but the file is non-functional. I wouldn't know where to start in analyzing "what's wrong with it?"
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  5. #5
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    I assume you got fd from either putting in the stdin/out file descriptors, or you obtained it through socket() or open().

  6. #6
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    I've always just used send() and recv() on sockets.

    gg

  7. #7
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    Ditto. But its not an uncommon practice to use fdopen() with sockets.

  8. #8
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Codeplug View Post
    I've always just used send() and recv() on sockets.
    Yes, it would seem irrefutable now.

    If anyone has time and can see what's wrong, this is the code:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <sys/un.h>
    #include <sys/stat.h>
    
    	
    short int loclconn (char *socket, int fd) { 
    	size_t size;
    	struct sockaddr_un peer;
    	peer.sun_family=AF_LOCAL;
    	strcpy(peer.sun_path,socket);
    	size=SUN_LEN(&peer);
    	return connect(fd,(struct sockaddr*)&peer,size);
    } 
    
    
    short int loclsckt (char *file) {
    	struct sockaddr_un name;
    	short int sock;
    	size_t size;
    
    	if ((strlen(file)) > 107) return -2;
    	if ((sock=socket(PF_LOCAL,SOCK_STREAM,0)) < 0) return -1;
    
    	name.sun_family = AF_LOCAL;	
    	strcpy(name.sun_path, file);	
    	size=SUN_LEN(&name);
    	if ((bind(sock,(struct sockaddr*)&name,size) < 0)) return -3;
    	return sock;
    }
    
    
    int main (int argc, char *argv[]) {
    	short int pid, CHLD, PARN, OUT, IN;
    	size_t len;
    	int bytes;
    	char *buffer, *buffer2;
    	struct stat finfo;
    	FILE *fstRO = fopen(argv[1], "rb"), * sstOUT;
    	FILE *fstW = fopen("/root/test/image.jpg", "wb");
    	struct sockaddr addr;
    
    	if (fstRO == NULL) {
    		puts("valid filename required");
    		return -1;}
    	
    	stat(argv[1],&finfo);
    	bytes=finfo.st_size;
    	buffer=malloc(bytes);
    	buffer2=malloc(bytes);
    	
    	printf("&#37;d\n",bytes);
    	
    	fread(buffer,bytes,1,fstRO);
    	fclose(fstRO);
    
    	pid=fork();
    	if (pid == 0) {
    		puts("child");
    		CHLD=loclsckt("/root/test/sock1");
    		OUT=loclconn("/root/test/sock2",CHLD);
    		if ((sstOUT=fdopen(OUT,"wb"))==NULL) perror("fdopen");
    		write(OUT,buffer,bytes);
    		close(OUT);
    		close(CHLD);
    		unlink("/root/test/sock1");
    		return;
    	} 
    	puts("parent");
    	PARN=loclsckt("/root/test/sock2");
    	listen(IN,0);
    	IN=accept(PARN,&addr,&len);
    	read(IN,buffer2,bytes);
    	close(IN);
    	close(PARN);
    	unlink("/root/test/sock2");
    
    	fwrite(buffer2,bytes,1,fstW);
    	fclose(fstW);
    }
    As is, it does everything I mentioned -- a normal read/write on the descriptors (producing a defuct file) and an attempt to create a stream on the child (send) descriptor, which fails and gives perror.
    Last edited by MK27; 10-08-2008 at 06:07 PM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  9. #9
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    Are you supposed to close a descriptor like that after using fdopen()? I am going to have to do a check. But methinks that is the problem.

  10. #10
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    The fdopen() function associates a stream with the existing file descriptor, fildes. The mode of the stream (one of the values "r", "r+", "w", "w+", "a", "a+") must be compatible with the mode of the file descriptor. The file position indicator of the new stream is set to that belonging to fildes, and the error and end-of-file indicators are cleared. Modes "w" or "w+" do not cause truncation of the file. The file descriptor is not dup'ed, and will be closed when the stream created by fdopen() is closed. The result of applying fdopen() to a shared memory object is undefined.
    You can stop pulling hair out of your head now. Just ditch the closing the handle line and you are good.

  11. #11
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    No, that's not the problem (I took all the closes out and it does the same thing). I don't see how closing descriptors and streams after you're done using them would matter.

    The only "unconventional" thing I did was to put the socket code in a function, which means the struct sockaddr stuff would be lost. I haven't tried putting that back into main because I assumed it doesn't matter after the socket is created/connected.

    Perhaps it is the "wb"...nope
    Last edited by MK27; 10-08-2008 at 05:02 PM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  12. #12
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    Why are you using a short int? This shouldn't be the problem, but I am also not going to say it can't be the problem.

  13. #13
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    I am going to be blunt, why are you even using fdopen to begin with? Your code doesn't really utilize its functionality.

  14. #14
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    No, don't take out the closes, just take out the fclose you fdopened.

  15. #15
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by master5001 View Post
    Why are you using a short int? This shouldn't be the problem, but I am also not going to say it can't be the problem.
    On my computer I am unlikely to recieve file descriptor 33454 (etc). But I tried switching "short int" to "int" -- same thing.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Header File Question(s)
    By AQWst in forum C++ Programming
    Replies: 10
    Last Post: 12-23-2004, 11:31 PM
  2. Creation of Menu problem
    By AQWst in forum C Programming
    Replies: 8
    Last Post: 11-24-2004, 09:44 PM
  3. Binary Search Trees Part III
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 10-02-2004, 03:00 PM
  4. Tutorial review
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 11
    Last Post: 03-22-2004, 09:40 PM
  5. Request for comments
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 01-02-2004, 10:33 AM