Sending html file with HTTP protocol over tcp and browser shows error

c++, html, http, network-programming, tcp

Solution

You have two important problems I can see

Your are passing `send` paremeters wrong, this line (very important)

int c=send(connected,(const char*)&sendBuffer,strlen(&writable[0]),0);

should be

int c=send(connected,(const char*) sendBuffer,strlen(&writable[0]),0);
/*                                ^ 
 *                                No ampersand
 */

since the `sendBuffer` array decays to a pointer and you don't need that.

You are passing the first parameter of `select` wrong too from the manual

nfds is the highest-numbered file descriptor in any of the three sets, plus 1

so in your case it should be

if (select(connected + 1, NULL, &wfd, NULL, &tm) > 0)

and you are using it after you call `send` you must call it before to see if it is possible to write to the file descriptor.

Your code is a little bit too complicated for the task it's designed to so I propose the following solution with the mentions problems fixed and some other ones improved

string       text;
stringstream stream;

FILE *sendFile = fopen("foo.html", "r");
if (sendFile == NULL) /* check it the file was opened */
    return;

fseek(sendFile, 0L, SEEK_END);
/* you can use a stringstream, it's cleaner */
stream << "HTTP/1.1 200 OK\nContent-length: " << ftell(sendFile) << "\n";
fseek(sendFile, 0L, SEEK_SET);

text = stream.str();
/* you don't need a vector and strcpy to a char array, just call the .c_str() member
 * of the string class and the .length() member for it's length
 */
send(connected, text.c_str(), text.length(), 0);

std::cout << "Sent : " <<  text << std::endl;

text = "Content-Type: text/html\n\n";
send(connected, text.c_str(), text.length(), 0);

std::cout << "Sent : %s" << text << std::endl;
while (feof(sendFile) == 0)
{
    int  numread;
    char sendBuffer[500];

    numread = fread(sendBuffer, sizeof(unsigned char), 300, sendFile);
    if (numread > 0)
    {
        char *sendBuffer_ptr;

        sendBuffer_ptr = sendBuffer;
        do {
            fd_set  wfd;
            timeval tm;

            FD_ZERO(&wfd);
            FD_SET(connected, &wfd);

            tm.tv_sec  = 10;
            tm.tv_usec = 0;
            /* first call select, and if the descriptor is writeable, call send */
            if (select(1 + connected, NULL, &wfd, NULL, &tm) > 0)
            {
                int numsent;

                numsent = send(connected, sendBuffer_ptr, numread, 0);
                if (numsent == -1)
                    return;
                sendBuffer_ptr += numsent;
                numread        -= numsent;
            }
        } while (numread > 0);
    }
}
/* don't forget to close the file. */
fclose(sendFile);

Problem

I'm am writing a HTTP web server when I send a text file with the equivalent content of the HTML file to the browser the browser shows it correctly but when I send the HTML file itself browser shows the HTML page for a second and then the "the connection was reset" error shows up. I have noticed that the text file is bigger than the HTML file but I have no Idea why text size = 286 byte HTML size = 142 byte and this is the HTML code: ``` <!DOCTYPE html> <html> <body> <p>This is a paragraph.</p> <p>This is a paragraph.</p> <p>This is a paragraph.</p> </body> </html> ``` this is my code: ``` char sendBuffer[500]; FILE *sendFile = fopen("foo.html", "r"); fseek(sendFile, 0L, SEEK_END); int sz = ftell(sendFile); fseek(sendFile, 0L, SEEK_SET); string s1; s1="HTTP/1.1 200 OK\nContent-length: " + to_string(sz) + "\n"; std::vector<char> writable(s1.begin(), s1.end()); writable.push_back('\0'); strcpy(sendBuffer,(const char *)&writable[0]); int c=send(connected,(const char*)&sendBuffer,strlen(&writable[0]),0); printf("\nSent : %s\n",sendBuffer); strcpy(sendBuffer,"Content-Type: text/html\n\n"); c=send(connected,(const char*)&sendBuffer,strlen("Content-Type: text/html\n\n"),0); printf("\nSent : %s\n",sendBuffer); char send_buffer[300]; while( !feof(sendFile) ) { int numread = fread(send_buffer, sizeof(unsigned char), 300, sendFile); if( numread < 1 ) break; // EOF or error char *send_buffer_ptr = send_buffer; do { int numsent = send(connected, send_buffer_ptr, numread, 0); if( numsent < 1 ) // 0 if disconnected, otherwise error { if( numsent < 0 ) { if( WSAGetLastError() == WSAEWOULDBLOCK ) { fd_set wfd; FD_ZERO(&wfd); FD_SET(connected, &wfd); timeval tm; tm.tv_sec = 10; tm.tv_usec = 0; if( select(0, NULL, &wfd, NULL, &tm) > 0 ) continue; } } break; // timeout or error } send_buffer_ptr += numsent; numread -= numsent; } while( numread > 0 ); } ``` Here is the other part of code that is used just before the code above: ``` int sock, connected, bytes_recieved , _true = 1 , portNumber; char send_data [1024] , recv_data[1024]; struct sockaddr_in server_addr,client_addr; int sin_size; time_t t = time(NULL); struct tm tm = *localtime(&t); char date[50]; if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("Unable to create the Socket"); exit(1); } if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(const char*)&_true,sizeof(int)) == -1) { perror("Unable to Setsockopt"); exit(1); } char *server_address="127.1.1.1"; portNumber=8080; server_addr.sin_family = AF_INET; server_addr.sin_port = htons(portNumber); server_addr.sin_addr.s_addr = inet_addr("127.1.1.1");//inet_pton(AF_INET,"127.0.0.1",&server_addr.sin_addr);//INADDR_ANY; string host=server_address+':'+to_string(portNumber); memset(&(server_addr.sin_zero),0,8);//sockaddr_in zero padding is needed if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr))==-1) //bind the socket to a local address { perror("Unable to bind"); exit(1); } if (listen(sock, 5) == -1) //listen to the socket with the specified waiting queue size { perror(" Listen"); exit(1); } cout << "MyHTTPServer waiting on port 8080" << endl; fflush(stdout); sin_size = sizeof(struct sockaddr_in); connected = accept(sock, (struct sockaddr *)&client_addr,&sin_size); cout<< "I got a connection from (" << inet_ntoa(client_addr.sin_addr) << "," << ntohs(client_addr.sin_port) << ')' << endl; ```

Original source