LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 06-30-2006, 08:10 AM   #1
introuble
Member
 
Registered: Apr 2004
Distribution: Debian -unstable
Posts: 700

Rep: Reputation: 31
sockets: Send string to server


Ok .. I have the following function, which writes to a socket:

Code:
void sockwrite(int sockd, const void *buf)
{
	char *ptr = (char *)buf;
	size_t bytesleft = strlen(ptr);
	size_t bytessent = 0;

	while (bytesleft > 0) {
		bytessent = Write(sockd, ptr, bytesleft);
		ptr += bytessent;
		bytesleft -= bytessent;
	}
}
Now, I need to use this function to send to the server a string of the form:

Code:
"PASSWORD <a password>\r\n"
<a password> is stored in "pass", it's a char string.

I can do this two ways:

Code:
#1.
        sockwrite(s, "PASSWORD ");
        sockwrite(s, pass);
        sockwrite(s, "\r\n");
Code:
#2.
        char *buffer;	
        asprintf(&buffer, "PASSWORD %s\r\n", pass);
        sockwrite(s, buffer);
This is not the only string of this type I have to send though. Chances are I'll have to send a lot of strings of similar form. Question is: which method do I use? The first won't allocate a temporary storage location but expands over 3 lines [loss of clarity?]. The 2nd is clearer but allocates a temporary storage location for the string AND asprintf() is not POSIX compliant [GNU extension, will work on Linux/BSD .. and I can live with that ]

So .. how should I do this? Any other methods?

Last edited by introuble; 06-30-2006 at 08:13 AM.
 
Old 06-30-2006, 12:48 PM   #2
burntfuse
Member
 
Registered: Sep 2005
Location: Laurel, MD, USA
Distribution: Slackware 10.1, FC5
Posts: 164

Rep: Reputation: 30
You could also keep a global buffer that's the length of the longest string you'll have to send, and then do:

Code:
sprintf(buffer, [whatever]);
sockwrite(s, buffer);
Yeah, it's a bit messy, but it would reduce the number of lines of code each time you do something like this. Altogether, your first way might be the best as long as you don't have to convert numbers to strings or anything that you'd need printf for. It isn't really any harder to read, and it saves memory.
 
Old 06-30-2006, 01:16 PM   #3
tuxdev
Senior Member
 
Registered: Jul 2005
Distribution: Slackware
Posts: 2,012

Rep: Reputation: 115Reputation: 115
Socket descripters are file descripters in *nix. Just use fprintf.
 
Old 06-30-2006, 01:20 PM   #4
graemef
Senior Member
 
Registered: Nov 2005
Location: Hanoi
Distribution: Fedora 13, Ubuntu 10.04
Posts: 2,379

Rep: Reputation: 148Reputation: 148
You probably don't need to send the third line \r\n since it doesn't really provide anything extra. In which case your first approach would probably be better.
 
Old 06-30-2006, 02:47 PM   #5
introuble
Member
 
Registered: Apr 2004
Distribution: Debian -unstable
Posts: 700

Original Poster
Rep: Reputation: 31
fprintf on a socket? No thanks.

I don't think a global, static allocated buffer is very memory savy/good practise.

The protocol requires that all messages end in "\r\n".

Well .. I guess I will indeed use the first method .. I suppose this gets rid of some portability problems [introducted by the use of asprintf].
 
Old 06-30-2006, 02:55 PM   #6
jlinkels
LQ Guru
 
Registered: Oct 2003
Location: Bonaire, Leeuwarden
Distribution: Debian /Jessie/Stretch/Sid, Linux Mint DE
Posts: 5,195

Rep: Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043
If I am not mistaken, the function sockwrite hangs when the connection is interrupted or times out. Should bytessent not checked for being zero to indicate that there is nothing sent at all? Or did you omit this for simplicity? (and be nice to us, readers)

jlinkels
 
Old 06-30-2006, 04:44 PM   #7
tuxdev
Senior Member
 
Registered: Jul 2005
Distribution: Slackware
Posts: 2,012

Rep: Reputation: 115Reputation: 115
Using fprintf on a socket is fine. In fact, *nix sockets are designed to be used that way. You should not be using threads anyway, so what is the big deal?
 
Old 07-01-2006, 04:51 AM   #8
introuble
Member
 
Registered: Apr 2004
Distribution: Debian -unstable
Posts: 700

Original Poster
Rep: Reputation: 31
Quote:
If I am not mistaken, the function sockwrite hangs when the connection is interrupted or times out. Should bytessent not checked for being zero to indicate that there is nothing sent at all? Or did you omit this for simplicity? (and be nice to us, readers)
Code:
bytessent = Write(sockd, ptr, bytesleft);
the Write() wrapper takes care of it.
 
Old 07-01-2006, 09:29 AM   #9
jlinkels
LQ Guru
 
Registered: Oct 2003
Location: Bonaire, Leeuwarden
Distribution: Debian /Jessie/Stretch/Sid, Linux Mint DE
Posts: 5,195

Rep: Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043
Doesn't write return 0 (zero) if no bytes are being written? And since bytessent is 0, your program will remain in the loop.

jlinkels
 
Old 07-01-2006, 02:04 PM   #10
introuble
Member
 
Registered: Apr 2004
Distribution: Debian -unstable
Posts: 700

Original Poster
Rep: Reputation: 31
Code:
ssize_t Write(int fd, const void *buf, size_t count)
{
        ssize_t nrbytes;

        if ((nrbytes = write(fd, buf, count)) == -1) {
                perror("write");
                exit(EXIT_FAILURE);
        }

        return nrbytes;
}
The purpoise of sockwrite() is to make sure buf is sent OR cause the program to exit.
 
Old 07-01-2006, 02:39 PM   #11
jlinkels
LQ Guru
 
Registered: Oct 2003
Location: Bonaire, Leeuwarden
Distribution: Debian /Jessie/Stretch/Sid, Linux Mint DE
Posts: 5,195

Rep: Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043
Introuble,

Ok, at first I failed to see that Write was a different function from write.

Now, I know that someone else's code is always worse that someone's own, but still a comment which is meant as good advice.

First, I doubt whether leaving the program because of a write failure is the best thing to do. But since you know your program requirements best, it might be according to your needs.

However, if for any reason you ever would want to take any action as a result of a write failure you would not be able to do so as your program already exited. No clean-up, no error messages, no action in case of a simple time-out.

As a matter of fact, recently there was some discussion in this thread about leaving the program in a deeply nested exit.
http://www.linuxquestions.org/questi...d.php?t=458107

Also, your write function only checks for a return code of -1. There might be more return codes, including zero, which are not detected in this way, and leave your program in a loop anyway.

I know this sounds pedantic, but from your fisrt post I got the idea you are trying to code as cleanly as possible, hence my two cents...

jlinkels
 
Old 07-02-2006, 12:26 AM   #12
introuble
Member
 
Registered: Apr 2004
Distribution: Debian -unstable
Posts: 700

Original Poster
Rep: Reputation: 31
write() [ Write() ] will only be used on a socket. And yes, if the call fails, the program must exit.

Code:
No clean-up, no error messages, no action in case of a simple time-out.
#1. If I *really* want to, I can use atexit(). I see no reason to design my program so that if an error which must cause an exit occurs, the function this error occured in would return to it's caller, which would in turn return to it's caller etc. untill main would be reached and the return/exit call would be made there. However, except for "good practise" [which, I have to say, this time, I don't quite comprehend as I don't use memory-leak detecting software ..], I don't see a point in freeing buffers before an exit and not leaving it to the operating system. The data contained in those buffers isn't "sensitive" anyway.

#2. What do you mean no error messages?

Code:
perror("write");

And about the reference to that other thread .. look who's the thread starter


I'm always opened to suggestions. I've decided to look at code from other programs that use the same protocol as my app to see how things are done. My opinion is I have familiarity with C but what I deeply miss is the "practical" part. No book taught how things are done "in real life", this is the reason why this thread exists. [and the one you made reference to]

[p.s.: expect a thread asking about a "how-to" study the source of a large program ]

Cheers.

Last edited by introuble; 07-02-2006 at 12:29 AM.
 
Old 07-02-2006, 01:31 AM   #13
paulsm4
LQ Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
Hi - my

1. Yes, I'd definitely encourage you to de-allocate all buffers before a *normal* exit, and *not* rely on the OS. It's just good discipline, if nothing else.

As far as an *abnormal* termination: that's different. No, I don't see any compelling reason to be anal as long as you're aborting the whole program.

2. As far as your original question, about concatenating a string:

a) I agree, global buffers probably aren't a great choice.

b) I also agree that "fprintf()" probably isn't a great choice, either (although tuxdev is right - there is absolutely *no* problem using fprintf with sockets under Linux).

c) So what's wrong with using three lines? That's fine; it's not at all unclear.

d) And what's wrong with doing an "sprintf()" (or the equivalent, for example "snprintf()") into a *stack* variable?

I honestly believe options c) and d) are equally clean, and perform equally well.

3. Finally (and what prompted me to write this) - a book recommendation:

Code Reading, Diomidis Spinellis
http://www.bookpool.com/ss?qs=code+reading

I honestly think you'll enjoy it!

Sincerely .. PSM

PS:
Was your "Write" wrapper inspired by Stevens?
 
Old 07-02-2006, 06:38 PM   #14
jlinkels
LQ Guru
 
Registered: Oct 2003
Location: Bonaire, Leeuwarden
Distribution: Debian /Jessie/Stretch/Sid, Linux Mint DE
Posts: 5,195

Rep: Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043
Quote:
Originally Posted by introuble
#2. What do you mean no error messages?

Code:
perror("write");
Ok, I confused perror with that other command which writes to the system log. I don't call that (the other one) an error message to the user, but perror does the job.



Quote:
Originally Posted by introuble
And about the reference to that other thread .. look who's the thread starter
Cheers.
Isn't it a small world?
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
cant send a whole struct with sockets (c code) alaios Programming 9 04-12-2020 09:52 AM
can't send files with sockets crapodino Programming 2 02-12-2006 07:29 AM
how can i send a file using linux sockets?? crapodino Programming 2 10-09-2005 11:17 PM
Sockets: multiple send() calls throttle server framerate. JCipriani Programming 3 09-22-2005 07:06 PM
sockets dont ever send data alaios Programming 1 09-21-2005 06:59 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 12:32 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration