socket connection problem

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Jeff Crouse

    socket connection problem

    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::writeD ata(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::writeD ata(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.

    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.m oderated. First time posters: Do this! ]
  • Daniel T.

    #2
    Re: socket connection problem

    google@jeffish. org (Jeff Crouse) wrote:
    [color=blue]
    > 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::writeD ata(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::writeD ata(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.[/color]

    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.

    Comment

    • Kevin Goodsell

      #3
      Re: socket connection problem

      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++.m oderated from the cross-post list.
      [color=blue]
      > 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'.[/color]

      Note that sockets are not part of standard C++ and are not topical here.
      [color=blue]
      >
      > The following code works just fine.
      >
      > void Macsock::writeD ata(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");[/color]

      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.
      [color=blue]
      > }
      >
      > But, obviously, it is not sending the desired string.
      >
      > The following code does not work.
      >
      > void Macsock::writeD ata(char *buffer, int fd)[/color]

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

      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.
      [color=blue]
      > strcpy(buf, buffer);[/color]

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

      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.
      [color=blue]
      > 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.[/color]

      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?).
      [color=blue]
      >
      > 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.[/color]

      I'm sure it has a lot to do with the use of illegal broken code... It
      shouldn't even compile.
      [color=blue]
      > 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.[/color]

      Sockets are off-topic, also.
      [color=blue]
      > 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.[/color]

      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
      --
      My email address is valid, but changes periodically.
      To contact me please use the address from a recent posting.

      Comment

      • Francis Glassborow

        #4
        Re: socket connection problem

        In article <50afaa52.03090 51151.620292a8@ posting.google. com>, Jeff
        Crouse <google@jeffish .org> writes[color=blue]
        >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::writeD ata(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::writeD ata(char *buffer, int fd)
        >{
        > char buf[strlen(buffer)];[/color]

        The number of elements (chars in this case) must be known at compile
        time as C++ and C are both statically typed languages.[color=blue]
        > 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.[/color]

        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.


        --
        Francis Glassborow ACCU
        64 Southfield Rd
        Oxford OX4 1PA +44(0)1865 246490
        All opinions are mine and do not represent those of any organisation


        [ See http://www.gotw.ca/resources/clcm.htm for info about ]
        [ comp.lang.c++.m oderated. First time posters: Do this! ]

        Comment

        • Rob Williscroft

          #5
          Re: socket connection problem

          Jeff Crouse wrote in news:50afaa52.0 309051151.62029 2a8
          @posting.google .com:
          [color=blue]
          >
          > void Macsock::writeD ata(char *buffer, int fd)
          > {
          > char buf[strlen(buffer)];[/color]

          This is 1 to short.
          [color=blue]
          > strcpy(buf, buffer);[/color]

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

          strcpy() just did this, and buf[ sizeof(buf) ] is 1 beyond
          the end of buf. All bets are now off!
          [color=blue]
          > 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.
          >[/color]

          void Macsock::writeD ata(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::writeD ata(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.
          --


          [ See http://www.gotw.ca/resources/clcm.htm for info about ]
          [ comp.lang.c++.m oderated. First time posters: Do this! ]

          Comment

          • Robb

            #6
            Re: socket connection problem

            In article <50afaa52.03090 51151.620292a8@ posting.google. com>,
            google@jeffish. org says...[color=blue]
            > The following code works just fine.
            >
            > void Macsock::writeD ata(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.
            >[/color]
            The 'message has a \0 at the end. I believe that's why it goes through.
            [color=blue]
            > The following code does not work.
            >
            > void Macsock::writeD ata(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");
            > }
            >[/color]
            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

            [ See http://www.gotw.ca/resources/clcm.htm for info about ]
            [ comp.lang.c++.m oderated. First time posters: Do this! ]

            Comment

            • Charles Burns

              #7
              Re: socket connection problem

              google@jeffish. org (Jeff Crouse) wrote in
              news:50afaa52.0 309051151.62029 2a8@posting.goo gle.com:

              [snip]
              [color=blue]
              >
              > The following code does not work.
              >
              > void Macsock::writeD ata(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...[/color]




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


              void Macsock::writeD ata(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.

              [ See http://www.gotw.ca/resources/clcm.htm for info about ]
              [ comp.lang.c++.m oderated. First time posters: Do this! ]

              Comment

              • Kevin Goodsell

                #8
                Re: socket connection problem

                Charles Burns wrote:
                [color=blue]
                >
                > void Macsock::writeD ata(char *buffer, int fd)
                > {
                > // compute # of bytes buffer data really uses
                >
                > const int nbufbytes = strlen(buffer) * sizeof(buffer[0]) ;[/color]

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

                -Kevin
                --
                My email address is valid, but changes periodically.
                To contact me please use the address from a recent posting.

                [ See http://www.gotw.ca/resources/clcm.htm for info about ]
                [ comp.lang.c++.m oderated. First time posters: Do this! ]

                Comment

                • Rob Williscroft

                  #9
                  Re: socket connection problem

                  Rob Williscroft wrote in news:Xns93EE828 0A82A2ukcoREMOV Efreenetrtw@
                  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.
                  [color=blue]
                  >
                  > 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::writeD ata(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");
                  > }
                  >
                  >[/color]

                  void Macsock::writeD ata(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.
                  --


                  [ See http://www.gotw.ca/resources/clcm.htm for info about ]
                  [ comp.lang.c++.m oderated. First time posters: Do this! ]

                  Comment

                  • Jeff Crouse

                    #10
                    Re: socket connection problem

                    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.

                    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
                    [ comp.lang.c++.m oderated. First time posters: Do this! ]

                    Comment

                    • Roger Orr

                      #11
                      Re: socket connection problem

                      "Jeff Crouse" <google@jeffish .org> wrote in message
                      news:50afaa52.0 309051151.62029 2a8@posting.goo gle.com...[color=blue]
                      > 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::writeD ata(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::writeD ata(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");
                      > }[/color]
                      [snip]

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

                      void Macsock::writeD ata(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::writeD ata(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::writeD ata(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
                      --
                      MVP in C++ at www.brainbench.com




                      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
                      [ comp.lang.c++.m oderated. First time posters: Do this! ]

                      Comment

                      • kanze@gabi-soft.fr

                        #12
                        Re: socket connection problem

                        Francis Glassborow <francis@robint on.demon.co.uk> wrote in message
                        news:<pvqP$cCQG bW$EwCo@robinto n.demon.co.uk>. ..[color=blue]
                        > In article <50afaa52.03090 51151.620292a8@ posting.google. com>, Jeff
                        > Crouse <google@jeffish .org> writes[color=green]
                        > >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'.[/color][/color]
                        [color=blue][color=green]
                        > >The following code works just fine.[/color][/color]
                        [color=blue][color=green]
                        > >void Macsock::writeD ata(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");
                        > >}[/color][/color]
                        [color=blue][color=green]
                        > >But, obviously, it is not sending the desired string.[/color][/color]
                        [color=blue][color=green]
                        > >The following code does not work.[/color][/color]
                        [color=blue][color=green]
                        > >void Macsock::writeD ata(char *buffer, int fd)
                        > >{
                        > > char buf[strlen(buffer)];[/color][/color]
                        [color=blue]
                        > The number of elements (chars in this case) must be known at compile
                        > time as C++ and C are both statically typed languages.[/color]

                        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:

                        std::vector< char > buf( buffer, buffer + strlen( buffer ) + 1 ) ;
                        [color=blue][color=green]
                        > > strcpy(buf, buffer);[/color][/color]

                        Declared as above, there is no need for the strcpy.
                        [color=blue][color=green]
                        > > buf[sizeof(buf)] = '\0';
                        > > if(write(fd, buf, sizeof(buf)) < 0 )
                        > > perror("writing on stream socket");
                        > >}[/color][/color]
                        [color=blue][color=green]
                        > >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.[/color][/color]
                        [color=blue]
                        > 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.[/color]

                        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,
                        [color=blue]
                        > 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.[/color]

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

                        --
                        James Kanze GABI Software mailto:kanze@ga bi-soft.fr
                        Conseils en informatique orientée objet/ http://www.gabi-soft.fr
                        Beratung in objektorientier ter Datenverarbeitu ng
                        11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16

                        [ See http://www.gotw.ca/resources/clcm.htm for info about ]
                        [ comp.lang.c++.m oderated. First time posters: Do this! ]

                        Comment

                        Working...