tags:

views:

61

answers:

2

More than likely a rookie question, but I'm looking for a printf-esque function for use in send over TCP sockets. This is for a simple chat server, specifically a modified version of the one in Beej's socket guide. I'm prepared to write my own, but before I do I want to make sure I'm not reinventing the wheel.

I'm looking for something native to C, not a library or something. I'm doing this as an intellectual pursuit, and using a ready-made library isn't going to teach me as well as messing up until I get it right and understand why.

Appreciation in advance for anyone who answers!

Edit: I'm currently using:

if(current_user->fs_id == sending_user->fs_id) {
    snprintf(server->current_buffer, buffer_size, "You said: %s", message);
} else {
    snprintf(server->current_buffer, buffer_size, "%s said: %s", sending_user->name, message);
}

if(send(current_user->fs_id, server->current_buffer, buffer_size, 0) == -1) {
    perror("Sending data");
}

I understand this isn't the best way to do it, that's part of what I'm fixing now.

+1  A: 

I assume that you would use snprintf (safer than sprintf) into a buffer and send that...

You could of course, wrap this up in a nice little variadac function.

dmckee
That's what I'm using now, just curious if there's one tailored specifically for send. I thought since there's an fprintf there might be one for sockets.
Codeacula
The stream oriented nature of file access makes it sensible to make a different printf implementation for that specific use. in the case of send, you must fill a buffer in any case. Send even lets you reuse that buffer for both. `fprintf` is not for programmer convenience, it is an actual space/performance optimization.
TokenMacGuy
The sockets library post-dates the c standard library, so it wasn't in there at the beginning, and it seems that no committee has seen fit to include it since (and that's the right choice, files are nearly universal, sockets are merely very, very common).
dmckee
@TokenMacGuy: Thank you for the clarification on why there's an fprintf. I hadn't considered that.
Codeacula
Socket output is a stream too, surely? Yes, you probably wan't to buffer your formatted output anyway, but the same applies to files. If your library is sending one character at a time to the output file, it is working unnecessarily slowly - these days the O/S cache will limit the damage, but it's still not a good thing. Of course the file I/O buffers probably aren't set up to suite your format string, so I can imagine an fprintf may work in stages sending multiple buffer-loads to the file, but again - a socket could benefit from the same avoid-the-extra-buffering-layer optimisation.
Steve314
+4  A: 

Use fdopen to make a FILE * corresponding to the socket, then fprintf to write to it.

R..
Interesting. Is there any "gotchas" associated with this outside of the types you might find working with normal files? Speed hits or the like? Edit: For example, send requires me to loop with it until the full contents are sent, right? Does this apply with fprintf in this manner?
Codeacula
Assuming it is a stream socket in blocking mode, fprintf will take care of any looping that is needed. The only "gotcha" is if you are using Windows; on Windows, sockets are not file descriptors as they are on every other OS.
mark4o
Thanks, mark4o. And as a followup, is doing so slower than using send/recv directly? Is it a noticeable difference?
Codeacula
See now, *this* is what happens if you rely on actual experience instead of guessing. Tsk, tsk. Disgraceful.
dmckee
@dmckee If you're being sarcastic, first :P. I'm going to end up doing it myself anyway, but it doesn't hurt to ask. If you're not...well, I'm actually confused by your reply, then.
Codeacula
@Codeacule: 100% pure, unadulterated sarcasm. Take actual experience over theory any day. That'll teach you the perils of accepting an answer quickly. Let go 24 hours so that all time zones can have a crack at it.
dmckee
@dmckee: I will, but I also want to ask because I'm looking to gain knowledge, and if my results are contrary to what I'm told, then it gives me a reason to find out why instead of assuming "this must be right".
Codeacula
As for speed, if you are calling fprintf multiple times this should actually be faster than calling snprintf+send each time, since the output will be buffered and the send system call will only be called when the buffer is full. (Of course, you can call fflush if you need to flush it prior to that. Or you can change the buffering with setvbuf.)
mark4o
@mark4o: I would only be calling fprintf when I needed to send, so I would have to flush implicitly each time or make the change as you stated.
Codeacula
If you don't want to have to think about flushing, you can use `setbuf` to disable buffering for the `FILE`. Another option, if you're on a POSIX 2008 or GNU system, is the new `dprintf` function which writes directly to a file descriptor.
R..
@R. That's exactly what I was looking for. Thank you.
Codeacula