Menu

Desperately tryingTCPStream as an http server

Help
Tim Hawes
2000-06-30
2000-07-01
  • Tim Hawes

    Tim Hawes - 2000-06-30

    I am new to both C++ and CommonC++. I am developing under Linux. I have taken a slightly modified version of the tcp.cpp demo to write a servlet. Netscape views the output flawlessly, but when I connect with KDE's KFM, it prompts me for an application to view it with. Now, since KFM works fine with any other webserver I have tried (even the obscure ones), either I have the wrong idea about using tcpstream for http services, or I am missing something in my code for a "proper" http server. Any and all help would be greatly appreciated, since I went with this library in hopes to find a simple servlet class for http. Here is my code:

    #include <iostream.h>
    #include <stdlib.h>
    #include <string.h>
    #include <cc++/macros.h>
    #include <cc++/thread.h>
    #include <cc++/socket.h>

    class Servlet : public TCPSocket
        {
            protected:
                bool OnAccept(InetHostAddress &ia, short port);

            public:
                Servlet(InetAddress &ia, int port);
        };

    Servlet::Servlet(InetAddress &ia, int port) : TCPSocket(ia, port)
        {
        };

    bool Servlet::OnAccept(InetHostAddress &ia, short port)
        {
            cout << "accepting from: " << ia << ":" << port << endl;;
            return true;
        }

    int main(int argc, char * argv[])
        {
            tcpstream tcp;
            InetAddress addr;
            unsigned short int port = 8080;

            char htmlStart[] = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"HTML4.dtd\"><HTML>\n<HEAD>\n \
                <LINK rel=\"stylesheet\" type=\"text/css\" href=\"http://info.dhhs.state.nc.us/style/Main.css\">\n \
                </HEAD>\n<BODY>\n";
        char htmlEnd[] = "\n</BODY>\n</HTML>\n";
        char greet[] = "<H1 align=\"center\">C++ Test Servlet</H1>\n";
        char input[500];
        char method[3];
               
            addr = "255.255.255.255";
            cout << "testing addr: " << addr << ":" << port << endl;
            addr = "127.0.0.1";
            cout << "binding for: " << addr << ":" << port << endl;

            try
                {
                    Servlet server(addr, port);
                    while(server.isPending())
                        {
                            tcp.open(server);
                           
                            tcp >> method;
                            tcp >> input;
                           
                            if ( strcmp(input,"/") == 0 )
                                {
                                    tcp << htmlStart << greet << htmlEnd;
                                }
                            else
                                {
                                    tcp << htmlStart << greet << "<B>Method used:</B> " << method << "<BR><B>Arguments:</B> " << input << htmlEnd;
                                }
                               
                            tcp.close();
                        }
                }
            catch(Socket *socket)
                {
                    short port;
                    InetAddress saddr = (InetAddress)socket->getPeer(&port);
                    cerr << "socket error " << saddr << ":" << port << endl;
                    cout << "error number " << socket->getErrorNumber() << endl;       
                    if(socket->getErrorNumber() == SOCKET_RESOURCE_FAILURE)
                        {
                            cerr << "bind failed; no resources" << endl;
                            exit(-1);
                        }
                    if(socket->getErrorNumber() == SOCKET_BINDING_FAILED)
                        {
                            cerr << "bind failed; port busy" << endl;
                            exit(-1);
                        }
                }
        }

     
    • Tim Hawes

      Tim Hawes - 2000-06-30

      There is something I should add to my last post. When I choose kedit from kfm to read what is returned from the servlet, I get the </BODY> </HTML> tags.
      Any ideas?

       
      • David Sugar

        David Sugar - 2000-06-30

        I suspect the issue is packet fragmentation.  Since you use "\n" rather than
        putting a << endl; to "flush" lines, and hence the entire message is sent as one "chunk" rather than flushed and sent as multiple tcp packets.  While I have no info on http protocol and client implimentations, I have seen similar problems with crude nttp parsers which were written on top of fgets redirected thru a socket descriptor which have problems when things are merged or not split between logical lines.  This has a lot to do with the underlying mechanics of how stdin and things line fgets/getline may interact with the low level read call.

        Other than that, it's possible you have some problem with the headers themselves.  I do not know what a "proper" http header should look like offhand, but one way to check might be to put a test page on an existing web server, telnet to it, and manually perform a get request and compare the result to your serverlet.

         
        • Tim Hawes

          Tim Hawes - 2000-07-01

          Well the endl's helped get all the data to kedit, but kfm still prompts  for an application. I have already telneted into various webservers and none of them send a header. Well, none of them send a header if all you do is issue a GET command.

          I did finally solve it. KFM was looking for the Content-type: text/html line. But this http header by itself was not good for either Netscape nor Internet Explorer. These two web browsers would respond to plain generic data responses from the server, and would display the Content-type: as part of the output. Adding the "HTTP 1.1 200 OK" line tells Netscape that an HTTP header follows and then no longer displays the Content-type line as part of the output.

          Thanks for your help.

           
    • Mattia Rossi

      Mattia Rossi - 2000-06-30

      Try adding the 'Content-Type: text/html' at the beginning of HtmlStart, before anything else

      Mattia

       
      • Tim Hawes

        Tim Hawes - 2000-07-01

        I had tried this before, and Content-type is just treated as regular output by Netscape and IE, while KFM is quite happy with it. I needed to add this line:
        HTTP 1.1 200 OK
        This warns Netscape that an http header will follow and then Netscape hides the Content-type line until it finds double endl's.

        Thanks for your reply.

         

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.