view son this program - Unix

This is a discussion on view son this program - Unix ; STATEMENT: A server program that echoes back to the client what the client says. it handles multiple clients using fork(). WHAT I WANT: some advices and views of yours for improvement. /* a fork server */ #include #include #include #include ...

+ Reply to Thread
Results 1 to 8 of 8

Thread: view son this program

  1. view son this program

    STATEMENT:

    A server program that echoes back to the client what the client says.
    it handles multiple clients using fork().


    WHAT I WANT:

    some advices and views of yours for improvement.



    /* a fork server */


    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include


    #define SERVER_IP "127.0.0.1"

    enum { BUFFSIZE = 100, MAX_CONNECTION = 25 };

    void echo_back( int );


    int main( int argc, char** argv )
    {
    int server_fd, accept_fd, my_port;
    struct sockaddr_in servaddr;
    char arrc[BUFFSIZE];

    pid_t childpid;

    memset( arrc, '\0', BUFFSIZE+1 );
    memset( &servaddr, '\0', sizeof(servaddr) );

    if( argc == 2 )
    {
    my_port = atoi( argv[1] );
    }
    else
    {
    fprintf( stderr, "USAGE: ./file PORT\n");
    exit( EXIT_FAILURE );
    }


    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons( my_port );
    inet_aton( SERVER_IP, &(servaddr.sin_addr) );


    if( -1 == (server_fd = socket(PF_INET, SOCK_STREAM, 0)) )
    {
    fprintf( stderr, "SOCKET() error\n" );
    exit( EXIT_FAILURE );
    }

    if( -1 == bind( server_fd, (struct sockaddr*) &servaddr, sizeof( struct sockaddr )) )
    {
    fprintf( stderr, "BIND() error\n" );
    exit( EXIT_FAILURE );
    }
    printf("bind()\n");

    if( -1 == listen( server_fd, MAX_CONNECTION ))
    {
    fprintf( stderr, "LISTEN() error\n" );
    exit( EXIT_FAILURE );
    }
    printf("listen()\n");

    /* now lets see what client has to say */

    for( ; ; )
    {
    if( (accept_fd = accept(server_fd, 0, 0)) == -1 )
    {
    fprintf( stderr, "ACCEPT() error\n" );
    exit( EXIT_FAILURE );
    }
    printf( " accept()\n");

    if( !(childpid = fork()) )
    {
    close(server_fd);
    echo_back( accept_fd );
    exit( 0 );
    }

    close( accept_fd );
    }



    return 0;
    }




    void echo_back( int sockfd )
    {
    char buf[BUFFSIZE+1];

    memset( buf, '\0', BUFFSIZE+1 );


    if( recv( sockfd, buf, BUFFSIZE+1, 0) == -1 )
    {
    fprintf( stderr, "RECV() error\n" );
    exit( EXIT_FAILURE );
    }

    if( send(sockfd, buf, BUFFSIZE+1, 0 ) == -1 )
    {
    fprintf( stderr, "SEND() error\n" );
    exit( EXIT_FAILURE );
    }
    }



    ============== client code =================
    /* a simple client to send a string to server
    * and then recieving some string back.
    *
    *
    */

    #include
    #include
    #include
    #include
    #include
    #include
    #include


    #define MY_SERVER "127.0.0.1"

    enum { ARRSIZE = 21 };

    int main( int argc, char** argv )
    {
    int sockfd, MY_PORT;
    struct sockaddr_in client_str;
    char arrc[ARRSIZE+1] = "I am clinton\n";


    printf("%s\n", arrc);

    if( argc == 2 )
    {
    MY_PORT = atoi( argv[1] );
    }
    else
    {
    fprintf(stderr, "I expect the port number as argument\n");
    exit( EXIT_FAILURE );
    }


    if( (sockfd = socket( PF_INET, SOCK_STREAM, 0 ) ) == -1 )
    {
    fprintf(stderr, "SOCKET ERROR: can not create socket\n");
    exit( EXIT_FAILURE );
    }



    client_str.sin_family = AF_INET;
    client_str.sin_port = htons(MY_PORT);
    client_str.sin_addr.s_addr = inet_addr( MY_SERVER );
    memset( client_str.sin_zero, '\0', sizeof( client_str.sin_zero ) );

    if( connect( sockfd, (struct sockaddr*) &client_str, sizeof( struct sockaddr)) == -1 )
    {
    fprintf(stderr, "CONNECT() error\n");
    exit( EXIT_FAILURE );
    }

    if( send( sockfd, arrc, ARRSIZE+1, 0 ) == -1 )
    {
    fprintf(stderr, "SEND() error!\n");
    exit( EXIT_FAILURE );
    }


    if( recv( sockfd, arrc, ARRSIZE+1, 0) == -1 )
    {
    fprintf(stderr, "RECV() error!\n");
    exit( EXIT_FAILURE );
    }

    printf("---------------------------------\n%s\n", arrc);

    while( 1 ); /* added just to keep the client running */


    return 0;

    }




    --
    http://lispmachine.wordpress.com/
    my email ID is @ the above blog.


  2. Re: view son this program

    arnuld wrote:

    > ...
    > enum { BUFFSIZE = 100, MAX_CONNECTION = 25 };
    > ...
    > char arrc[BUFFSIZE];
    > ...
    > memset( arrc, '\0', BUFFSIZE+1 );


    You're initialising a chunk of memory that is longer than
    the sizeof(arrc) ... therefore you're overwriting something
    that doesn't belong to arrc ... this can invoke undefined behaviour.

  3. Re: view son this program

    Rainer Temme writes:
    > arnuld wrote:
    >
    >> ...
    >> enum { BUFFSIZE = 100, MAX_CONNECTION = 25 };
    >> ...
    >> char arrc[BUFFSIZE];
    >> ...
    >> memset( arrc, '\0', BUFFSIZE+1 );

    >
    > You're initialising a chunk of memory that is longer than
    > the sizeof(arrc) ... therefore you're overwriting something
    > that doesn't belong to arrc ... this can invoke undefined behaviour.


    The behaviour is undefined as of ISO-C. In practice, this will
    overwrite the first byte of whatever is behind arrc on the stack with
    a 0, which is harmless.


  4. Re: view son this program

    Rainer Weikusat wrote:
    > Rainer Temme writes:
    > > arnuld wrote:
    > >
    > >> ...
    > >> enum { BUFFSIZE = 100, MAX_CONNECTION = 25 };
    > >> ...
    > >> char arrc[BUFFSIZE];
    > >> ...
    > >> memset( arrc, '\0', BUFFSIZE+1 );

    > >
    > > You're initialising a chunk of memory that is longer than
    > > the sizeof(arrc) ... therefore you're overwriting something
    > > that doesn't belong to arrc ... this can invoke undefined behaviour.


    > The behaviour is undefined as of ISO-C. In practice, this will
    > overwrite the first byte of whatever is behind arrc on the stack with
    > a 0, which is harmless.


    s/is/can be/

    if you're lucky. It could as well smash the return address or
    another already initialized variable or whatever else comes
    directly after the arrc array, which in practice is not too
    unlikely too happen.
    Regards, Jens
    --
    \ Jens Thoms Toerring ___ jt@toerring.de
    \__________________________ http://toerring.de

  5. Re: view son this program

    jt@toerring.de (Jens Thoms Toerring) writes:
    > Rainer Weikusat wrote:
    >> Rainer Temme writes:
    >> > arnuld wrote:
    >> >
    >> >> ...
    >> >> enum { BUFFSIZE = 100, MAX_CONNECTION = 25 };
    >> >> ...
    >> >> char arrc[BUFFSIZE];
    >> >> ...
    >> >> memset( arrc, '\0', BUFFSIZE+1 );
    >> >
    >> > You're initialising a chunk of memory that is longer than
    >> > the sizeof(arrc) ... therefore you're overwriting something
    >> > that doesn't belong to arrc ... this can invoke undefined behaviour.

    >
    >> The behaviour is undefined as of ISO-C. In practice, this will
    >> overwrite the first byte of whatever is behind arrc on the stack with
    >> a 0, which is harmless.

    >
    > s/is/can be/
    >
    > if you're lucky. It could as well smash the return address or
    > another already initialized variable or whatever else comes
    > directly after the arrc array, which in practice is not too
    > unlikely too happen.


    Ehh ... yes. But not in this code. IMHO, to understand why this is a
    really bad thing, it is necessary to first understand what it is (most
    likely) going to do and why 'everything works' nevertheless in this
    particular case.

  6. Re: view son this program

    On Thu, 29 May 2008 22:35:17 +0200, Rainer Weikusat wrote:

    > jt@toerring.de (Jens Thoms Toerring) writes:
    >> Rainer Weikusat wrote:
    >>> Rainer Temme writes:
    >>> > arnuld wrote:
    >>> >
    >>> >> ...
    >>> >> enum { BUFFSIZE = 100, MAX_CONNECTION = 25 }; ...
    >>> >> char arrc[BUFFSIZE];
    >>> >> ...
    >>> >> memset( arrc, '\0', BUFFSIZE+1 );
    >>> >
    >>> > You're initialising a chunk of memory that is longer than the
    >>> > sizeof(arrc) ... therefore you're overwriting something that doesn't
    >>> > belong to arrc ... this can invoke undefined behaviour.

    >>
    >>> The behaviour is undefined as of ISO-C. In practice, this will
    >>> overwrite the first byte of whatever is behind arrc on the stack with
    >>> a 0, which is harmless.

    >>
    >> s/is/can be/
    >>
    >> if you're lucky. It could as well smash the return address or another
    >> already initialized variable or whatever else comes directly after the
    >> arrc array, which in practice is not too unlikely too happen.

    >
    > Ehh ... yes. But not in this code. IMHO, to understand why this is a
    > really bad thing, it is necessary to first understand what it is (most
    > likely) going to do and why 'everything works' nevertheless in this
    > particular case.


    Well, it *is* a bad thing to write to a memory location that does not
    belong to an allocated object. In this case the memset() isn't even needed
    (some people initialize character arrays to zero to make strxxx()
    functions to behave correctly. For mysterious reasons obviously).

    Better would be to inspect the returnvalue from read()// recvfrom and
    *not* trust on the target string to be nul-terminated (for the wrong
    reasons).
    Also, the unintended behavior differs between systems, depending on the
    fact of the stack growing either up or down.
    A Deathstation 3000 (choose your favorite version number) could start
    launching rockets directed at the wrong targets, or start calculating
    prime numbers, or whatever it chooses.

    HTH,
    AvK

  7. Re: view son this program

    Moi writes:
    > On Thu, 29 May 2008 22:35:17 +0200, Rainer Weikusat wrote:
    >> jt@toerring.de (Jens Thoms Toerring) writes:
    >>> Rainer Weikusat wrote:
    >>>> Rainer Temme writes:
    >>>> > arnuld wrote:
    >>>> >
    >>>> >> ...
    >>>> >> enum { BUFFSIZE = 100, MAX_CONNECTION = 25 }; ...
    >>>> >> char arrc[BUFFSIZE];
    >>>> >> ...
    >>>> >> memset( arrc, '\0', BUFFSIZE+1 );
    >>>> >
    >>>> > You're initialising a chunk of memory that is longer than the
    >>>> > sizeof(arrc) ... therefore you're overwriting something that doesn't
    >>>> > belong to arrc ... this can invoke undefined behaviour.
    >>>
    >>>> The behaviour is undefined as of ISO-C. In practice, this will
    >>>> overwrite the first byte of whatever is behind arrc on the stack with
    >>>> a 0, which is harmless.
    >>>
    >>> s/is/can be/
    >>>
    >>> if you're lucky. It could as well smash the return address or another
    >>> already initialized variable or whatever else comes directly after the
    >>> arrc array, which in practice is not too unlikely too happen.

    >>
    >> Ehh ... yes. But not in this code. IMHO, to understand why this is a
    >> really bad thing, it is necessary to first understand what it is (most
    >> likely) going to do and why 'everything works' nevertheless in this
    >> particular case.

    >
    > Well, it *is* a bad thing to write to a memory location that does not
    > belong to an allocated object.


    It is often a programming error. It is even often a programming error
    which can cause effects which appear quite bizarre and are really hard
    to track down and fix. But understanding what is going to happen at
    the machine code level for a particular, simple situation is IMO
    required to understand why this is a serious error, *despite* it does
    not impede the functionality of this particular program as it is now
    on the author's machine.

    [...]

    > A Deathstation 3000 (choose your favorite version number) could
    > start launching rockets directed at the wrong targets,


    Assuming a computer which actually controls missiles, I am fairly
    convinced that "my software has just killed ten million people because
    the C-standard did not demand that it won't" would not be a very
    practical defense in front of a criminal or civil court.

  8. Re: view son this program

    > On Thu, 29 May 2008 16:27:18 +0200, Rainer Temme wrote:

    >> arnuld wrote:
    >> ...
    >> enum { BUFFSIZE = 100, MAX_CONNECTION = 25 };
    >> ...
    >> char arrc[BUFFSIZE];
    >> ...
    >> memset( arrc, '\0', BUFFSIZE+1 );


    > You're initialising a chunk of memory that is longer than
    > the sizeof(arrc) ... therefore you're overwriting something
    > that doesn't belong to arrc ... this can invoke undefined behaviour.



    oh.. that must be: char arrc[BUFFSIZE+1];


    --
    http://lispmachine.wordpress.com/
    my email ID is @ the above blog.


+ Reply to Thread