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; ```