Question

I'm recently learning how to program a basic webserver in c. My server depending on certain inputs will send various lines of text all which end in a blank line, and I need to recieve them from the client side somehow to display one line at a time.

Right now the server does something like

send(socket, sometext, strlen(sometext), 0)
send ...
send(socket, "\n", 2, 0);

....

Client:

Currently what I am doing is using fdopen to wrap the socket file descriptor and read with fgets:

FILE *response = fdopen(someSocket, "r");
while(1){
            fgets(input, 500, response);

        if(strcmp(input, "\n") != 0){
            //do some stuff
        }
        else {
            // break out of the loop
            break;
        }
}

This all works well except my program need to fulfil one condition, and that is to not break the socket connection ever. Because I opened a file, in order to stop memory leak the next line after is:

fclose(response);

This however is the root of my problems because it not only closes the file but also closes the socket, which I can't have. Can anyone give me any guidence on simple methods to work around this? I was thinking about maybe using recv() but doesn't that have to take in the whole message all at once? Is there any way to recreate the behavior of fgets using recv?

I'm really a newbie at all this, thanks for all the help!

Was it helpful?

Solution

Your only real alternative is to write a function that:

1) calls recv() with a fixed buffer and a loop,

2) only returns when you get a complete line (or end-of-connection)

3) saves any "leftover characters for the next read of the next line of text

IIRC, Stevens has such a function:

PS: Any self-respecting higher-level web programming library will give you a "getNextLine()" function basically for free.

OTHER TIPS

The other problem you have is that the FILE may have read more data (past the blank line) from your socket and buffered it, which will be lost if you close the FILE. The solution to both problems is to NOT close the FILE -- simply create a single FILE with fdopen when you first create the socket (immediately after the connect or accept call), and use that for all data reads from the socket.

One other note: send(socket, "\n", 2, 0); will send a newline AND a nul -- you probably want send(socket, "\n", 1, 0); or send(socket, "\n\n", 2, 0); depending on what the other sends are doing.

You should try sending the HTTP headers, wich in turn will tell your client about the length of the content and so on. This way you don't have to check for any linebreaks.

http://en.wikipedia.org/wiki/List_of_HTTP_header_fields

POSIX has a function getline(3) that you might find useful here. It lives in stdio.h, and the prototype is

ssize_t getline(char ** restrict linep, size_t * restrict linecapp, FILE * restrict stream);

It'll even resize the buffer (via realloc(3)) to be large enough to hold the line.

There's also fgetln(3) which is similar, and is also available in a wide character version. It's not standard, however.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top