Professional Web Applications Themes

Redirecting Default Output to a Socket - UNIX Programming

Hi All, I'm developing a simple web server. to send a reply to the client, I have to first put it into a buffer and then use send() to send it. For example: int clientSocket = accept (ServerSocket, ...); char *buf = "<h1>Hello using send()</h1>; send(clientSocket, buf, strlen(buf), 0); works just fine. However, it is rather tedious if you have to send so many different messages. So I thought it would be more practical just to set the default output to clientSocket and use printf directly as follows: int clientSocket = accept (ServerSocket, ...); dup2(clientSocket, fileno(stdout)); printf("Hello using printf()"); For ...

  1. #1

    Default Redirecting Default Output to a Socket

    Hi All,

    I'm developing a simple web server. to send a reply
    to the client, I have to first put it into a buffer
    and then use send() to send it. For example:

    int clientSocket = accept (ServerSocket, ...);
    char *buf = "<h1>Hello using send()</h1>;
    send(clientSocket, buf, strlen(buf), 0);

    works just fine. However, it is rather tedious if
    you have to send so many different messages. So I
    thought it would be more practical just to set the
    default output to clientSocket and use printf
    directly as follows:

    int clientSocket = accept (ServerSocket, ...);
    dup2(clientSocket, fileno(stdout));
    printf("Hello using printf()");

    For some reason, this doesn't work. Eventhough I
    don't get any errors, the message doesn't get passed
    to the client.

    Can someone please explain why this doesn't work and,
    if possible, how it can be modified to work?

    Thanks.


    -ammar

    Email: alsayegh at purdue dot edu




    Ammar Guest

  2. #2

    Default Re: Redirecting Default Output to a Socket

    "Ammar T. Al-Sayegh" <replace-dot-with-real-dot> writes:
     
     

    Does it work if you add this:

    fflush(stdout);

    If it does, "man setvbuf" and
    "man setlinebuf" <<- this is probably what you want.

    Cheers,
    --
    In order to understand recursion you must first understand recursion.
    Paul Guest

  3. #3

    Default Re: Redirecting Default Output to a Socket

    On Sat, 11 Oct 2003 22:15:08 +0000, Ammar T. Al-Sayegh wrote:
     

    You might want to look at...

    http://freshmeat.net/projects/cheetahd/

    ....this is 569 lines in a single file. While it's far from perfect, it
    does work and will give you some idea of what you want/need to do.
     

    Define "get any errors"...

    1. In the example you aren't checking what printf() returns.
    2. You are calling dup2() for fileno(stdout) and calling printf(), this is
    completely undefined behavior and I'd actually hope that libc would
    ignore it (but it probably doesn't).
    3. The data may or may not have gone down any underlying fd in the
    printf()s.
     

    Well you could check all the return values, Call fdopen() instead of what
    you are doing, and then use fprintf() and call fclose() and check the
    return value from that too when you want to end the connection.
    However while this gets you some form of "formatted output"[1] it
    requires using blocking IO[2] and doing a lot of tests for fprintf()
    errors. So IMO the only way to do what you want is to use a real string/IO
    library[3]. This would often directly translate the pseudo-ish code...

    fd = accept();
    if (fd == -1) err(EXIT_FAILURE, "accept");

    ADT_get(s1, fd);
    if (ADT_cmp_eq(s1, "GET "))
    {
    ADT_fmt(s2, "%d header stuff...", 404);
    ADT_fmt(s2, "more %s stuff...", "and more");
    ADT_fmt(s2, "stuff...");
    }
    /* ... */
    if (ADT_alloc_error(s2))
    errno = ENOMEM, err(EXIT_FAILURE, "data");
    /* ... */
    ADT_put(s2, fd); // Use in a non-blocking loop

    ....which looks close to what you want.

    [1] Using the system printf can be a non-portable thing to do.

    [2] You're doing blocking-io for simplicity right? See...
    http://www.and.org/texts/network_io.html

    [3] And here's one I prepared earlier...

    --
    James Antill -- org
    Need an efficient and powerful string library for C?
    http://www.and.org/vstr/

    James Guest

  4. #4

    Default Re: Redirecting Default Output to a Socket

    # int clientSocket = accept (ServerSocket, ...);
    # dup2(clientSocket, fileno(stdout));
    # printf("Hello using printf()");
    #
    # For some reason, this doesn't work.

    I wouldn't expect it to work either. You're playing nasty and unnecessary
    games behind stdio's back; don't expect it to realise what you have done.

    Instead use the function stdio provides to do this, fdopen.
    int clientSocket = ... ;
    FILE *client = fdopen(clientSocket,"r+");
    setvbuf(...); /*as desired*/
    And then you can use fprintf, fgets, fscanf, and all the rest of stdio
    freely and effectively.

    --
    Derk Gwen http://derkgwen.250free.com/html/index.html
    Who's leading this mob?
    Derk Guest

  5. #5

    Default Re: Redirecting Default Output to a Socket

    "Paul Pluzhnikov" <net> wrote in message news:net... 

    >
    > Does it work if you add this:
    >
    > fflush(stdout);[/ref]

    Yes, it does!

     

    I did setlinebuf(stdout) before calling printf().
    ssflush() is no longer needed.

    Many thanks!


    -ammar


    Ammar Guest

  6. #6

    Default Re: Redirecting Default Output to a Socket

    "Derk Gwen" <com> wrote in message news:supernews.com... 

    setlinebuf() solved the problem by itself. I also noticed
    that:

    cout << "Hello using cout stream" << endl;

    worked without setlinebuf() or fflush(). However:

    cout << "Hello using cout stream";

    didn't work with setlinebuf by itself. I had to add fflush()
    to get it to work.

    That leads me to the following question: If I can redirect
    cout stream to the socket, then would it also be possible
    to make the socket file descriptor to behave like stream?
    So, instead of redirecting default output to a socket and
    then sending the message to cout, would it be possible to
    do something like:

    int clientSocket = accept (ServerSocket, ...);
    ostream clientSocketStream = create_output_stream(clientSocket);
    clientOutputStream << "Hello using socket stream" << endl;

    It would be very nice if I could do something like that
    because I'm doing a multi-threaded server and I don't
    want to redirect the default output to one socket while
    other messages are being sent to other sockets in other
    threads.

     

    I can see that this construct might be more applicable
    to multi-threaded servers, since I can create different
    file descriptors for the different sockets in the threads.
    However, would it be possible to apply that to output
    streams?

    Thanks.


    -ammar


    Ammar Guest

Similar Threads

  1. Replies: 1
    Last Post: September 8th, 10:58 AM
  2. redirecting the output of a command to a file
    By Marcos Rebelo in forum PERL Beginners
    Replies: 1
    Last Post: August 26th, 04:26 PM
  3. Redirecting the output of Scheduled Tasks
    By John in forum Windows Setup, Administration & Security
    Replies: 2
    Last Post: July 25th, 08:57 AM
  4. Error when redirecting output to Excel
    By Tammy B. in forum ASP
    Replies: 1
    Last Post: July 4th, 12:54 PM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139