# fprintf on a socket



## bsd_newbie (Feb 12, 2009)

I have some code that is sending output to stdout. I'd like to send
it over a socket. Can I cast the socket descriptor to FILE * using fdopen and call fprintf with FILE * as the first parameter.

thanks.
bsd_newbie


----------



## Djn (Feb 12, 2009)

I would expect so - if it looks like a file, you should be able to treat it as one.

Try?


----------



## dh (Feb 12, 2009)

No you can't do such thing, FILE is a struct and not a int like socket descrioptors are.
You could however associate a FILE struct with descriptor using fdopen() function:

```
int fd = socket(AF_INET, SOCK_STREAM, 0);
FILE *fp = fdopen(fd, "r+");
```

However, I would take another path and use snprintf() to format string and use regular write() call to send it.


----------



## dh (Feb 12, 2009)

Oh nevermind, I didn't read orignal post carefully enough... you already mentioned fdopen().


----------



## anemos (Feb 12, 2009)

You can do 
	
	



```
close(1);
```
 which will free stdout's file descriptor and and then use dup(yoursocket). 
Try it and let us know if it works. Also, it would be good if you post some code.


----------



## mjguzik (Feb 12, 2009)

Duplicating new descriptor as 1 and then using it with FILE *stdout looks really ugly. (If I misunderstood you, then I'm sorry.) Far better is to use fdopen and freopen later. (Altrough it doesn't seem that this is necessary in this case.)


----------



## anemos (Feb 12, 2009)

```
close(1);
dup(sockfd);
```

will free file descriptor 1 from stdout and will attach sockfd to it.
Then, the output of, let's say:

```
printf("Bubbaloo");
```
will be automatically redirected to the socket.
Until of course the program ends where the file descriptor is being freed up again (this is not definite however).


----------



## mjguzik (Feb 12, 2009)

This is dup2() in short.  bsd_newbie wanted FILE * type so my point is still valid. (And printf() internally uses FILE *stdout too.)


----------



## anemos (Feb 12, 2009)

mjguzik said:
			
		

> This is dup2() in short.


Either dup() or dup2() does the job.




> bsd_newbie wanted FILE * type so my point is still valid. (And printf() internally uses FILE *stdout too.)



This is the magic with UNIX. Everything is treated/seen as a file!

Cheers


----------



## mjguzik (Feb 12, 2009)

By FILE I mean http://codepad.org/61Jj7Ilw . Just changing the associated descriptor may or may not work correctly, in either case it doesn't look like the right way. freopen() would take care of it I believe.


----------



## dap (Feb 12, 2009)

bsd_newbie asked about using *f*printf(), so he or she doesn't need to redirect stdout or STDOUT_FILENO.
Personnally I would use this solution:


			
				dh said:
			
		

> However, I would take another path and use snprintf() to format string and use regular write() call to send it.



Because this way you still can easily control how many bytes will be sent on the socket.


----------



## fonz (Feb 12, 2009)

dap said:
			
		

> bsd_newbie asked about using *f*printf()



The way I read the OP's question, it pretty much comes down to: "How can I write to a socket instead of stdout?"

That being said, I think the snprintf()()/write()() idea is indeed the easier, more elegant solution. And possibly more secure too, exactly for the reason you mentioned.

Alphons


----------



## SirDice (Feb 13, 2009)

bsd_newbie said:
			
		

> I have some code that is sending output to stdout. I'd like to send it over a socket.



Have a look at the netcat source. 

http://www.freebsd.org/cgi/cvsweb.cgi/src/contrib/netcat/


----------



## bsd_newbie (Feb 14, 2009)

Thanks for all those who replied. Finally I used this idea with more specific examples from Linux socket programming chap 10 "using standard IO on sockets". fdopen is fine but make sure you use different streams for input and output...
File *rx;
File *tx;

            rx = fdopen(s, "r");
            if ( !rx ) {
                /* Failed */
                close(clsd);
                continue;
            }
            tx = fdopen(dup(s), "w");
            if (!tx) {
                fclose(rx);
                continue;
            }
            setlinebuf(rx);
            setlinebuf(tx);

            ...............
............................

sometime later...
            fclose(tx);
            shutdown(fileno(rx), SHUT_RDWR);
            fclose(rx);


----------

