socket connection problem

J

Jeff Crouse

In my project, I have successfully opened a sock_stream style socket
connection between two processes and am trying to send 'buffer' to a
connected client, 'fd'.

The following code works just fine.

void Macsock::writeData(char *buffer, int fd)
{
char message[] = "This is a message from the front.";
if(write(fd, message, sizeof(message)) < 0 )
perror("writing on stream socket");
}

But, obviously, it is not sending the desired string.

The following code does not work.

void Macsock::writeData(char *buffer, int fd)
{
char buf[strlen(buffer)];
strcpy(buf, buffer);
buf[sizeof(buf)] = '\0';
if(write(fd, buf, sizeof(buf)) < 0 )
perror("writing on stream socket");
}

I'm sure that this very simple code is horrifying to any C programmer,
but I am not a C programmer, I'm just a hack trying to get something
finished. All of the stcpy stuff was done because the connected
client I mentioned is very picky about messages being terminated by a
null character.

Any suggestions as to why the string in the function parameter would
cause a problem, whereas the string declared in the function does not
would be greatly appreciated. I welcome any other questions about my
situation (I'm sure I have forgotten something important), but I would
like to avoid questions about the client, as it is not written in C++
and is therefore off-topic. Suffice to say, it has been tested with
other hosts and works just fine. I am 99% sure that the problem is
with the host, not the client.
 
D

Daniel T.

In my project, I have successfully opened a sock_stream style socket
connection between two processes and am trying to send 'buffer' to a
connected client, 'fd'.

The following code works just fine.

void Macsock::writeData(char *buffer, int fd)
{
char message[] = "This is a message from the front.";
if(write(fd, message, sizeof(message)) < 0 )
perror("writing on stream socket");
}

But, obviously, it is not sending the desired string.

The following code does not work.

void Macsock::writeData(char *buffer, int fd)
{
char buf[strlen(buffer)];
strcpy(buf, buffer);
buf[sizeof(buf)] = '\0';
if(write(fd, buf, sizeof(buf)) < 0 )
perror("writing on stream socket");
}

I'm sure that this very simple code is horrifying to any C programmer,
but I am not a C programmer, I'm just a hack trying to get something
finished. All of the stcpy stuff was done because the connected
client I mentioned is very picky about messages being terminated by a
null character.

Any suggestions as to why the string in the function parameter would
cause a problem, whereas the string declared in the function does not
would be greatly appreciated. I welcome any other questions about my
situation (I'm sure I have forgotten something important), but I would
like to avoid questions about the client, as it is not written in C++
and is therefore off-topic. Suffice to say, it has been tested with
other hosts and works just fine. I am 99% sure that the problem is
with the host, not the client.

Try this:


#include <iostream>
using namespace std;

int main() {
char message[] = "This is a message from the front.";
char* buf = message;
cout << sizeof( message ) << endl;
cout << sizeof( buf ) << endl;
cout << strlen( message ) << endl;
cout << strlen( buf ) << endl;
}

The output of the above should point you in the right direction.
 
K

Kevin Goodsell

Jeff Crouse wrote:

Please don't cross-post to moderated groups. It prevents the message
from reaching non-moderated groups in a timely manner. I've removed
comp.lang.c++.moderated from the cross-post list.
In my project, I have successfully opened a sock_stream style socket
connection between two processes and am trying to send 'buffer' to a
connected client, 'fd'.

Note that sockets are not part of standard C++ and are not topical here.
The following code works just fine.

void Macsock::writeData(char *buffer, int fd)
{
char message[] = "This is a message from the front.";
if(write(fd, message, sizeof(message)) < 0 )
perror("writing on stream socket");

Are you quite sure that write() will set errno? If not, you'd better
first set errno to 0, then test it afterward and only use perror if
errno is non-0.

write() is not a standard function, so we can't say much about it here.
}

But, obviously, it is not sending the desired string.

The following code does not work.

void Macsock::writeData(char *buffer, int fd)

Are you sure const char *buffer would not be better?
{
char buf[strlen(buffer)];

Array sizes must be compile-time constants. Even if this worked, the
array is not large enough for the string you want to copy into it.
strcpy(buf, buffer);

Because 'buf' is too small, this will overwrite memory you don't own,
causing undefined behavior (probably crashing your program or corrupting
data).
buf[sizeof(buf)] = '\0';

The indices for 'buf' (if buf were properly declared) go from 0 to
sizeof(buf)-1, so you are writing past the end of the array here. That
causes undefined behavior. This is pretty basic C++ array stuff - if you
don't understand it, you'd better return to studying for a while before
you attempt to use arrays or do anything non-trivial with the language.

And here's a question: Why are you attempting to copy the array at all?
You could probably just pass in the original - I'm guessing write won't
change it.
if(write(fd, buf, sizeof(buf)) < 0 )
perror("writing on stream socket");
}

I'm sure that this very simple code is horrifying to any C programmer,
but I am not a C programmer, I'm just a hack trying to get something
finished. All of the stcpy stuff was done because the connected
client I mentioned is very picky about messages being terminated by a
null character.

Well, in the second example you aren't even attempting to send the null
character, as far as I can tell. You have a char array long enough for
the string but not the null terminator. Then you send using sizeof(buf)
as the size argument (presumably - I'm only guessing since you use a
non-standard function). That has no chance of sending a null character,
which was written past the end of the buf array (maybe - undefined
behavior, so who knows what actually happened?).
Any suggestions as to why the string in the function parameter would
cause a problem, whereas the string declared in the function does not
would be greatly appreciated.

I'm sure it has a lot to do with the use of illegal broken code... It
shouldn't even compile.
I welcome any other questions about my
situation (I'm sure I have forgotten something important), but I would
like to avoid questions about the client, as it is not written in C++
and is therefore off-topic.

Sockets are off-topic, also.
Suffice to say, it has been tested with
other hosts and works just fine. I am 99% sure that the problem is
with the host, not the client.

You mean the code you post? Uh, yeah, I'd say there's some problems with it.

Why are you using C-style arrays anyway? If you had used std::string
instead, pretty much all of your problems would have magically
disappeared. But it would still be a good idea for you to review how
arrays work to avoid problems in the future.

-Kevin
 
F

Francis Glassborow

Jeff said:
In my project, I have successfully opened a sock_stream style socket
connection between two processes and am trying to send 'buffer' to a
connected client, 'fd'.

The following code works just fine.

void Macsock::writeData(char *buffer, int fd)
{
char message[] = "This is a message from the front.";
if(write(fd, message, sizeof(message)) < 0 )
perror("writing on stream socket");
}

But, obviously, it is not sending the desired string.

The following code does not work.

void Macsock::writeData(char *buffer, int fd)
{
char buf[strlen(buffer)];

The number of elements (chars in this case) must be known at compile
time as C++ and C are both statically typed languages.
strcpy(buf, buffer);
buf[sizeof(buf)] = '\0';
if(write(fd, buf, sizeof(buf)) < 0 )
perror("writing on stream socket");
}

I'm sure that this very simple code is horrifying to any C programmer,
but I am not a C programmer, I'm just a hack trying to get something
finished. All of the stcpy stuff was done because the connected
client I mentioned is very picky about messages being terminated by a
null character.

Actually a C programmer would take one look, note the :: and ignore the
rest because it isn't C. A C++ programmer sees everything else and
immediately wonders why a member function of Macsock is being defined
with an attempt at writing pure C.

Are you responsible for the Macsock class? If so you need to find help
from someone who understands the fundamentals of class design. If not
you need to throw it away and find a good implementation. Frankly the
above code is so far from reasonable C++ in both design and
implementation that the writer of it needs to first learn about the
available tools provided by C++ (std::string, std::fstream etc.) before
attempting a redesign and fresh implementation. Alternatively you need
to find a good third party implementation of a socket class that meets
your needs.
 
R

Rob Williscroft

Jeff Crouse wrote in @posting.google.com:
void Macsock::writeData(char *buffer, int fd)
{
char buf[strlen(buffer)];

This is 1 to short.
strcpy(buf, buffer);

You just wrote buffer and its terminating '\0' to the buf
buf[sizeof(buf)] = '\0';

strcpy() just did this, and buf[ sizeof(buf) ] is 1 beyond
the end of buf. All bets are now off!
if(write(fd, buf, sizeof(buf)) < 0 )
perror("writing on stream socket");
}

I'm sure that this very simple code is horrifying to any C programmer,
but I am not a C programmer, I'm just a hack trying to get something
finished. All of the stcpy stuff was done because the connected
client I mentioned is very picky about messages being terminated by a
null character.

void Macsock::writeData(char *buffer, int fd)
{
if( write( fd, buffer, strlen( buffer ) + 1 ) < 0 )
perror("writing on stream socket");
}

strlen() counts the nuber of char before it finds a '\0'. So
if buffer doesn't have one the above will not do what you want.


void Macsock::writeData(char *buffer, size_t size, int fd)
{
char buf[ size + 1 ];
strncpy( buf, buffer, size );
buf[ size ] = 0;
if( write( fd, buffer, strlen( buf ) ) < 0 )
perror("writing on stream socket");
}

Take Note of the "+ 1"'s in both of the above examples.

HTH

Rob.
 
R

Robb

The following code works just fine.

void Macsock::writeData(char *buffer, int fd)
{
char message[] = "This is a message from the front.";
if(write(fd, message, sizeof(message)) < 0 )
perror("writing on stream socket");
}

But, obviously, it is not sending the desired string.
The 'message has a \0 at the end. I believe that's why it goes through.
The following code does not work.

void Macsock::writeData(char *buffer, int fd)
{
char buf[strlen(buffer)];
strcpy(buf, buffer);
buf[sizeof(buf)] = '\0';
if(write(fd, buf, sizeof(buf)) < 0 )
perror("writing on stream socket");
}
Here nothing is known about the 'buffer'.
Since you use strcpy and stlen, the message in 'buffer' should be
terminated by \0. Is it?
Maybe the first char in 'buffer' is a \0?

Robb
 
C

Charles Burns

(e-mail address removed) (Jeff Crouse) wrote in

[snip]
The following code does not work.

void Macsock::writeData(char *buffer, int fd)
{
char buf[strlen(buffer)];
strcpy(buf, buffer);
buf[sizeof(buf)] = '\0';
if(write(fd, buf, sizeof(buf)) < 0 )
perror("writing on stream socket");
}

Any suggestions...




You bet it doesnt work. Try this (assuming "buffer" is NULL terminated")


void Macsock::writeData(char *buffer, int fd)
{
// compute # of bytes buffer data really uses

const int nbufbytes = strlen(buffer) * sizeof(buffer[0]) ;


// write buffer to socket

if ( write ( fd, buffer, nbufbytes ) != nbufbytes ) {

perror("writing on stream socket");

}
}




Good day to you.
 
K

Kevin Goodsell

Charles said:
void Macsock::writeData(char *buffer, int fd)
{
// compute # of bytes buffer data really uses

const int nbufbytes = strlen(buffer) * sizeof(buffer[0]) ;

sizeof(buffer[0]) == sizeof(char) == 1, so why bother? You also forgot
to add 1 for the null character.

-Kevin
 
R

Rob Williscroft

Rob Williscroft wrote in 195.129.110.130:

Strange the things you miss, see one error ignore the rest.
I really need a newsreader with a compile before send feature.
strlen() counts the nuber of char before it finds a '\0'. So
if buffer doesn't have one the above will not do what you want.


void Macsock::writeData(char *buffer, size_t size, int fd)
{
char buf[ size + 1 ];
strncpy( buf, buffer, size );
buf[ size ] = 0;
if( write( fd, buffer, strlen( buf ) ) < 0 )
perror("writing on stream socket");
}

void Macsock::writeData(char *buffer, size_t size, int fd)
{
std::string buf( buffer, size );
if( write( fd, buf.c_str(), buf.size() ) < 0 )
perror("writing on stream socket");
}


Rob.
 
J

Jeff Crouse

Many thanks to all of you who have helped me. It was a great success.

Now, just to respond to a couple of things for my own sake...

-I apologize for cross-posting the message where I shouldn't have. It
won't happen again.
-This was not my own code, but code that I inherited from a mysterious
previous developer.
-The +1's saved the day, and I feel ready to take on the world with my
new inderstanding of sizeof()
-I realize that sockets are not on-topic in this forum, and I was
originally going to post it in a C group, but i thought class
structure might be part of the problem, so I put it here. What should
I have done?

Again, I am very grateful for your help.
 
R

Roger Orr

Jeff Crouse said:
In my project, I have successfully opened a sock_stream style socket
connection between two processes and am trying to send 'buffer' to a
connected client, 'fd'.

The following code works just fine.

void Macsock::writeData(char *buffer, int fd)
{
char message[] = "This is a message from the front.";
if(write(fd, message, sizeof(message)) < 0 )
perror("writing on stream socket");
}

But, obviously, it is not sending the desired string.

The following code does not work.

void Macsock::writeData(char *buffer, int fd)
{
char buf[strlen(buffer)];
strcpy(buf, buffer);
buf[sizeof(buf)] = '\0';
if(write(fd, buf, sizeof(buf)) < 0 )
perror("writing on stream socket");
}
[snip]

Leaving aside the actual code let's look at the interface:

void Macsock::writeData(char *buffer, int fd)

My question is: how does you know the length of the buffer?

If "buffer" is a C style string, that is, it ends with a NUL character then
you can write data directly from buffer, as long as you remember to write
the NUL character too:-

void Macsock::writeData(char *buffer, int fd)
{
if ( write(fd, buffer, strlen(buffer) + 1)) < 0 )
...
}

Note the +1 - this ensures the final NUL is written.

In the case where buffer is not NUL terminated you'll need another parameter
to writeData to supply the length of 'buffer'.
You'll then need to dynamically allocate memory to copy 'buffer' into and
add a NUL.
Alternatively you can write 'length' bytes from buffer and then write a
single NUL character.

void Macsock::writeData(char *buffer, int length, int fd)
{
static const char nul = '\0';
if ( ( write( fd, buffer, length ) < 0 ) ||
( write( fd, &nul, 1 ) < 0 ) )
...
}

HTH,
Roger Orr
 
K

kanze

Francis Glassborow said:
Jeff said:
In my project, I have successfully opened a sock_stream style socket
connection between two processes and am trying to send 'buffer' to a
connected client, 'fd'.
The following code works just fine.
void Macsock::writeData(char *buffer, int fd)
{
char message[] = "This is a message from the front.";
if(write(fd, message, sizeof(message)) < 0 )
perror("writing on stream socket");
}
But, obviously, it is not sending the desired string.
The following code does not work.
void Macsock::writeData(char *buffer, int fd)
{
char buf[strlen(buffer)];
The number of elements (chars in this case) must be known at compile
time as C++ and C are both statically typed languages.

That's true for C++ (the subject here), but not for C99, where this
definition is perfectly legal.

In C++, of course, we would write something like:


Declared as above, there is no need for the strcpy.
buf[sizeof(buf)] = '\0';
if(write(fd, buf, sizeof(buf)) < 0 )
perror("writing on stream socket");
}
I'm sure that this very simple code is horrifying to any C
programmer, but I am not a C programmer, I'm just a hack trying to
get something finished. All of the stcpy stuff was done because the
connected client I mentioned is very picky about messages being
terminated by a null character.
Actually a C programmer would take one look, note the :: and ignore
the rest because it isn't C. A C++ programmer sees everything else and
immediately wonders why a member function of Macsock is being defined
with an attempt at writing pure C.

There could be various reasons why the interface might use char const*.
Why char*, I don't know; even in C, I would write char const*.
Internally, if I really did need the copy, I would obviously use
std::vector, and not char[]. In this case, however, I wonder why the
copy is even necessary. The simple expression:

if ( write( fd, buffer, strlen( buffer ) + 1 ) < 0 ) {
// ...
}

should do the trick.

However,
Are you responsible for the Macsock class? If so you need to find help
from someone who understands the fundamentals of class design. If not
you need to throw it away and find a good implementation. Frankly the
above code is so far from reasonable C++ in both design and
implementation that the writer of it needs to first learn about the
available tools provided by C++ (std::string, std::fstream etc.)
before attempting a redesign and fresh implementation. Alternatively
you need to find a good third party implementation of a socket class
that meets your needs.

This is really the critical advice. If you don't know a language, it is
hopeless trying to maintain code in it.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,141
Messages
2,570,817
Members
47,365
Latest member
BurtonMeec

Latest Threads

Top