Get HTML of url link with Visual Studio - html

The code below works for the main site, but it does not work for the sub-links. For example, the code works when the url link is "www.reddit.com" or "www.wikipedia.org" but it will not work when it is "www.reddit.com/r/nba" or "www.wikipedia.org/wiki/2007_NASCAR_Nextel_Cup_Series" Do you know how to make it work to include sub-links as well?
#include "stdafx.h"
#include <winsock2.h>
#include <WS2tcpip.h>
#include <windows.h>
#include <iostream>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
int main(){
// Initialize Dependencies to the Windows Socket.
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
cout << "WSAStartup failed.\n";
system("pause");
return -1;
}
// We first prepare some "hints" for the "getaddrinfo" function
// to tell it, that we are looking for a IPv4 TCP Connection.
struct addrinfo hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET; // We are targeting IPv4
hints.ai_protocol = IPPROTO_TCP; // We are targeting TCP
hints.ai_socktype = SOCK_STREAM; // We are targeting TCP so its SOCK_STREAM
// Aquiring of the IPv4 address of a host using the newer
// "getaddrinfo" function which outdated "gethostbyname".
// It will search for IPv4 addresses using the TCP-Protocol.
struct addrinfo* targetAdressInfo = NULL;
DWORD getAddrRes = getaddrinfo("www.wikipedia.org/wiki/2007_NASCAR_Nextel_Cup_Series", NULL, &hints, &targetAdressInfo);
if (getAddrRes != 0 || targetAdressInfo == NULL)
{
cout << "Could not resolve the Host Name" << endl;
system("pause");
WSACleanup();
return -1;
}
// Create the Socket Address Informations, using IPv4
// We dont have to take care of sin_zero, it is only used to extend the length of SOCKADDR_IN to the size of SOCKADDR
SOCKADDR_IN sockAddr;
sockAddr.sin_addr = ((struct sockaddr_in*) targetAdressInfo->ai_addr)->sin_addr; // The IPv4 Address from the Address Resolution Result
sockAddr.sin_family = AF_INET; // IPv4
sockAddr.sin_port = htons(80); // HTTP Port: 80
// We have to free the Address-Information from getaddrinfo again
freeaddrinfo(targetAdressInfo);
// Creation of a socket for the communication with the Web Server,
// using IPv4 and the TCP-Protocol
SOCKET webSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (webSocket == INVALID_SOCKET)
{
cout << "Creation of the Socket Failed" << endl;
system("pause");
WSACleanup();
return -1;
}
// Establishing a connection to the web Socket
cout << "Connecting...\n";
if (connect(webSocket, (SOCKADDR*)&sockAddr, sizeof(sockAddr)) != 0)
{
cout << "Could not connect";
system("pause");
closesocket(webSocket);
WSACleanup();
return -1;
}
cout << "Connected.\n";
// Sending a HTTP-GET-Request to the Web Server
const char* httpRequest = "GET / HTTP/1.1\r\nHost: www.google.com\r\nConnection: close\r\n\r\n";
int sentBytes = send(webSocket, httpRequest, strlen(httpRequest), 0);
if (sentBytes < strlen(httpRequest) || sentBytes == SOCKET_ERROR)
{
cout << "Could not send the request to the Server" << endl;
system("pause");
closesocket(webSocket);
WSACleanup();
return -1;
}
// Receiving and Displaying an answer from the Web Server
char buffer[10000];
ZeroMemory(buffer, sizeof(buffer));
int dataLen;
while ((dataLen = recv(webSocket, buffer, sizeof(buffer), 0) > 0))
{
int i = 0;
while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r') {
cout << buffer[i];
i += 1;
}
}
// Cleaning up Windows Socket Dependencies
closesocket(webSocket);
WSACleanup();
system("pause");
return 0;
}

You have to replace your GET / with GET /path/you/want/to/access.html and leave the server name as www.wikipedia.org but for heavens sake use WinHttpClient or Curl or something else more hi-level.

A URL is built by protocol, host and link. e.g. protocol://host/link --> http://www.wikipedia.org/wiki/2007_NASCAR_Nextel_Cup_Series. Here, http is the protocol, www.wikipedia.org is the host and /wiki/2007_NASCAR_Nextel_Cup_Series is the link.
Web Browsers internally split those parts up and then establish a Connection. e.g
http --> use port 80
www.wikipedia.org --> search for host and establish Connection
link (Here Comes the interesting part) --> Send the link through the TCP Connection as header
With a raw TCP Connection you can't directly open URL liks, you Need to send the link through the TCP Connection as Header. Or you use the Standart WebClients which do it for you.
I think the ultimate Problem is that you are trying to establish a TCP Connection with the entire URL instead of just the host.

Related

How to get the URL from a localhost server without using libcurl

I've made a custom HTTP server that serves an HTML page with some text, an input text box for entering a command, and a submit button. Upon receiving a form submission, the server is supposed to run the given command and serve a response containing the results.
The issue I cant quite figure out is how to get the URLs of form submission requests so as to parse out the command to run. As presently implemented, the server runs on localhost:3838, and when the client browses to that URL the server responds correctly with the form. When the user enters (say) the command ls in the text box and clicks the "run" submission button, a request is issued to localhost:3838/run?command=ls. How can I obtain that URL in the server, so as to parse out and execute the command?
Here's the present server code:
CwebServer.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#define PORT "3838" //port being connected to
#define MAXLEN 800
#define BACKLOG 10 //number of pending connections to be held in queue
//format of html page
char header []=
"HTTP/1.1 200 Ok\r\n"
"Content-Type: text/html; charset=UTF-8\r\n\r\n"
"<!DOCTYPE html>\r\n"
"<html>\n"
"<head>\n"
"<title>Web-Based Remote Command Server</title>\r\n"
"</head>\n"
"<body>\n\n";
char input []=
"<form action= \"/run\" method= \"GET\"> \n"
"Command: <input type=\"text\" size=\"100\" name=\"command\">\n"
"<input type=\"submit\" value=\"Run\">\n"
"</form>";
char output []=
"<p>Command that was run and testing this:</p>\n"
"<pre>Your server will include the command that was just run here.</pre>\n\n"
"<p>Standard Output:</p>\n""<pre>Your server will include the stdout results here.</pre>\n\n"
"<p>Standard Error:</p>\n"
"<pre>Your server will include the stderr results here.</pre>\r\n\r\n"
"</body>\r\n""</html>\r\n";
char *buff = header;
void sigchld_handler(int s)
{
(void)s; // quiet unused variable warning
// waitpid() might overwrite errno, so we save and restore it:
int saved_errno = errno;
while(waitpid(-1, NULL, WNOHANG) > 0);
errno = saved_errno;
}
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int main (void){
int sockfd;
int new_fd;
struct addrinfo hints;
struct addrinfo *serverinfo;
struct addrinfo *p;
struct sockaddr_storage client_addr;
socklen_t addrsize;
struct sigaction sa;
int yes = 1;
char s[INET6_ADDRSTRLEN];
int status;
memset(&hints, 0, sizeof hints); //makes struct empty
hints.ai_family = AF_UNSPEC; //IPv4 or v6
hints.ai_socktype = SOCK_STREAM; //TCP type need
hints.ai_flags = AI_PASSIVE; //Fill in IP for us
//if can't get address info print error
if((status = getaddrinfo(NULL, PORT, &hints, &serverinfo)) != 0){
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
return 1;
}
for(p = serverinfo; p != NULL; p = p->ai_next){
if((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1){
perror("server: socket");
continue;
}
if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1){
perror("setsockopt");
exit(1);
}
if(bind(sockfd, p->ai_addr, p->ai_addrlen) == -1){
close(sockfd);
perror("server: bind");
continue;
}
break;
}
freeaddrinfo(serverinfo);
if(p == NULL){
fprintf(stderr, "server: failed to bind\n");
exit(1);
}
if(listen(sockfd, BACKLOG) == -1){
perror("listen");
exit(1);
}
sa.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
exit(1);
}
printf("server: waiting for connections....\n");
while(1){
addrsize = sizeof client_addr;
new_fd = accept(sockfd, (struct sockaddr *)&client_addr, &addrsize);
if(new_fd == -1){
perror("Did not accept");
continue;
}
inet_ntop(client_addr.ss_family, get_in_addr((struct sockaddr *)&client_addr), s, sizeof s);
printf("server: got connection from %s\n", s);
if(!fork()){
close(sockfd);
int bufsize = 1024;
char *buffer = malloc(bufsize);
send(new_fd, header, bufsize, 0);
//write(new_fd, "HTTP/1.1 200 OK\n", 16);
//write(new_fd, "Content-length: 46\n", 19);
//write(new_fd, "Content-type: text/html\n\n", 25);
//write(new_fd, "<html><head>\n<head>\n<title>The CAvengers Web Page</title>\n</head>\n</html>", 46);
if(send(new_fd, buffer, MAXLEN, 0) == -1)
perror("send");
close(new_fd);
exit(0);
}
close(new_fd);
}
return 0;
}
Web servers and clients communicate via the HTTP protocol. That's what makes them web servers as opposed to some other kind. HTTP is a request / response protocol: the client sends a request to the server that contains information about what it's requesting, and the server processes that request to determine how to respond.
Your particular server seems to intend to implement HTTP 1.1. This is not the most recent version of the protocol, but that's ok. Pretty much every HTTP client in the world understands that dialect. But yours is a pretty minimally-functioning server, responding to every established connection with the same HTTP response, even if the client does not actually send an HTTP request.
Your question is how to get the request URI. The answer is to read it from the client, via the connected socket returned by accept(). The read() or recv() function would be appropos for that. The format you should expect the client to use is described in the HTTP specifications I linked above, but in very brief, you should expect the request to start with the request method name (GET), at least one space, the request URI, and a carriage-return / linefeed pair. You will need to parse the request URI to distinguish between an initial request for the form and a form submission, and in the latter case you will be able to parse the query parameters as well.
DO NOTE, however, that although HTTP is a comparatively simple protocol, it is still much more complicated than I've just described.

Server displaying text instead of HTML

I'm attempting to make a C server that will take inputs and be able to spit them back out to the user via html format where the server works as a user interface. My current issue I cant seem to figure out is why the C server spits out the HTML code as text at localhost:3838 instead of displaying it as a proper web page.
How can I solve this and have it be able to work to send user commands back to the server and spit out the proper response? Do I do this by using recieve and then putting the message into a buffer, parsing that message, and then putting that response into a buffer to send back using send?
CSERVER.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#define PORT "3838" //port being connected to
#define MAXLEN 800
#define BACKLOG 10 //number of pending connections to be held in queue
//format of html page
char header []=
"<!DOCTYPE html>\n"
"<html>\n"
"<head>\n"
"<title>Web-Based Remote Command Server</title>\n"
"</head>\n"
"<body>\n\n";
char input []=
"<form action= \"/run\" method= \"get\"> \n"
"Command: <input type=\"text\" size=\"100\" name=\"command\">\n"
"<input type=\"submit\" value=\"Run\">\n"
"</form>";
char output []= "<p>Command that was run:</p>\n"
"<pre>Your server will include the command that was just run here.</pre>\n\n"
"<p>Standard Output:</p>\n""<pre>Your server will include the stdout results here.</pre>\n\n"
"<p>Standard Error:</p>\n"
"<pre>Your server will include the stderr results here.</pre>\n\n"
"</body>\n""</html>";
char *buff = header;
void sigchld_handler(int s)
{
(void)s; // quiet unused variable warning
// waitpid() might overwrite errno, so we save and restore it:
int saved_errno = errno;
while(waitpid(-1, NULL, WNOHANG) > 0);
errno = saved_errno;
}
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int main (void){
int sockfd;
int new_fd;
struct addrinfo hints;
struct addrinfo *serverinfo;
struct addrinfo *p;
struct sockaddr_storage client_addr;
socklen_t addrsize;
struct sigaction sa;
int yes = 1;
char s[INET6_ADDRSTRLEN];
int status;
memset(&hints, 0, sizeof hints); //makes struct empty
hints.ai_family = AF_UNSPEC; //IPv4 or v6
hints.ai_socktype = SOCK_STREAM; //TCP type need
hints.ai_flags = AI_PASSIVE; //Fill in IP for us
//if can't get address info print error
if((status = getaddrinfo(NULL, PORT, &hints, &serverinfo)) != 0){
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
return 1;
}
for(p = serverinfo; p != NULL; p = p->ai_next){
if((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1){
perror("server: socket");
continue;
}
if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1){
perror("setsockopt");
exit(1);
}
if(bind(sockfd, p->ai_addr, p->ai_addrlen) == -1){
close(sockfd);
perror("server: bind");
continue;
}
break;
}
freeaddrinfo(serverinfo);
if(p == NULL){
fprintf(stderr, "server: failed to bind\n");
exit(1);
}
if(listen(sockfd, BACKLOG) == -1){
perror("listen");
exit(1);
}
sa.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
exit(1);
}
printf("server: waiting for connections....\n");
while(1){
addrsize = sizeof client_addr;
new_fd = accept(sockfd, (struct sockaddr *)&client_addr, &addrsize);
if(new_fd == -1){
perror("Did not accept");
continue;
}
inet_ntop(client_addr.ss_family, get_in_addr((struct sockaddr *)&client_addr), s, sizeof s);
printf("server: got connection from %s\n", s);
if(!fork()){
close(sockfd);
int bufsize = 1024;
char *buffer = malloc(bufsize);
recv(new_fd, buffer, bufsize, 0);
write(new_fd, "HTTP/1.1 200 OK\n", 16);
write(new_fd, "Content-length: 46\n", 19);
write(new_fd, "Content-type: text/html\n\n", 25);
write(new_fd, "<html><head>\n<title>The Web Page</title>\n</head>\n</html>", 46);
if(send(new_fd, header, MAXLEN, 0) == -1)
perror("send");
close(new_fd);
exit(0);
}
close(new_fd);
}
return 0;
}
You need to add the response headers like this one :
for example the response header send by SO for this page is:
HTTP/2.0 200 OK
cache-control: private
content-type: text/html; charset=utf-8
content-encoding: gzip
x-frame-options: SAMEORIGIN
x-request-guid: 599a5768-3cc6-4b94-86e1-e1d1daa8acd5
strict-transport-security: max-age=15552000
content-security-policy: upgrade-insecure-requests
accept-ranges: bytes
date: Tue, 07 May 2019 13:17:15 GMT
via: 1.1 varnish
x-served-by: cache-lcy19237-LCY
x-cache: MISS
x-cache-hits: 0
x-timer: S1557235035.073229,VS0,VE89
vary: Accept-Encoding,Fastly-SSL
x-dns-prefetch-control: off
content-length: 35669
X-Firefox-Spdy: h2

C:HTTP webserver - the image "http://localhost.... cannot be displayed because it contains errors

It's my first time dabbling with socket programming and I stumbled upon this amazing code from https://dzone.com/articles/web-server-c.
WHAT WE NEED TO DO: implement a simple HTTP web server that uses the web browser(input from the user) as a client
Here it is:
/*
* WebServer.c
*
* Created on: Nov 3, 2012
* Author: pavithra
*
* A web server in C language using only the standard libraries.
* The port number is passed as an argument.
*
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/sendfile.h>
#define EOL "\r\n"
#define EOL_SIZE 2
typedef struct {
char *ext;
char *mediatype;
} extn;
//Possible media types
extn extensions[] ={
{"gif", "image/gif" },
{"txt", "text/plain" },
{"jpg", "image/jpg" },
{"jpeg","image/jpeg"},
{"png", "image/png" },
{"ico", "image/ico" },
{"zip", "image/zip" },
{"gz", "image/gz" },
{"tar", "image/tar" },
{"htm", "text/html" },
{"html","text/html" },
{"php", "text/html" },
{"pdf","application/pdf"},
{"zip","application/octet-stream"},
{"rar","application/octet-stream"},
{0,0} };
//find webroot, add design
/*
A helper function
*/
void error(const char *msg) {
perror(msg);
exit(1);
}
/*
A helper function
*/
int get_file_size(int fd) {
struct stat stat_struct;
if (fstat(fd, &stat_struct) == -1)
return (1);
return (int) stat_struct.st_size;
}
/*
A helper function
*/
void send_new(int fd, char *msg) {
int len = strlen(msg);
if (send(fd, msg, len, 0) == -1) {
printf("Error in send\n");
}
}
/*
This function recieves the buffer
until an "End of line(EOL)" byte is recieved
*/
int recv_new(int fd, char *buffer) {
char *p = buffer; // Use of a pointer to the buffer rather than dealing with the buffer directly
int eol_matched = 0; // Use to check whether the recieved byte is matched with the buffer byte or not
while (recv(fd, p, 1, 0) != 0) // Start receiving 1 byte at a time
{
if (*p == EOL[eol_matched]) // if the byte matches with the first eol byte that is '\r'
{
++eol_matched;
if (eol_matched == EOL_SIZE) // if both the bytes matches with the EOL
{
*(p + 1 - EOL_SIZE) = '\0'; // End the string
return (strlen(buffer)); // Return the bytes recieved
}
} else {
eol_matched = 0;
}
p++; // Increment the pointer to receive next byte
}
return (0);
}
/*
A helper function: Returns the
web root location.
*/
char* webroot() {
// open the file "kill.txt" for reading
FILE *in = fopen("kill.txt", "rt");
// read the first line from the file
char buff[1000];
fgets(buff, 1000, in);
// close the stream
fclose(in);
char* nl_ptr = strrchr(buff, '\n');
if (nl_ptr != NULL)
*nl_ptr = '\0';
return strdup(buff);
}
/*
Handles php requests
*/
void php_cgi(char* script_path, int fd) {
send_new(fd, "HTTP/1.1 200 OK\n Server: Web Server in C\n Connection: close\n");
dup2(fd, STDOUT_FILENO);
char script[500];
strcpy(script, "SCRIPT_FILENAME=");
strcat(script, script_path);
putenv("GATEWAY_INTERFACE=CGI/1.1");
putenv(script);
putenv("QUERY_STRING=");
putenv("REQUEST_METHOD=GET");
putenv("REDIRECT_STATUS=true");
putenv("SERVER_PROTOCOL=HTTP/1.1");
putenv("REMOTE_HOST=127.0.0.1");
execl("/usr/bin/php-cgi", "php-cgi", NULL);
}
/*
This function parses the HTTP requests,
arrange resource locations,
check for supported media types,
serves files in a web root,
sends the HTTP error codes.
*/
int connection(int fd) {
char request[500], resource[500], *ptr;
int fd1, length;
if (recv_new(fd, request) == 0) {
printf("Receive Failed\n");
}
printf("%s\n", request);
// Check for a valid browser request
ptr = strstr(request, " HTTP/");
if (ptr == NULL) {
printf("NOT HTTP !\n");
} else {
*ptr = 0;
ptr = NULL;
if (strncmp(request, "GET ", 4) == 0) {
ptr = request + 4;
}
if (ptr == NULL) {
printf("Unknown Request ! \n");
} else {
if (ptr[strlen(ptr) - 1] == '/') {
strcat(ptr, "test.html");
}
strcpy(resource, webroot());
strcat(resource, ptr);
char* s = strchr(ptr, '.');
int i;
for (i = 0; extensions[i].ext != NULL; i++) {
if (strcmp(s + 1, extensions[i].ext) == 0) {
fd1 = open(resource, O_RDONLY, 0);
printf("Opening \"%s\"\n", resource);
if (fd1 == -1) {
printf("404 File not found Error\n");
send_new(fd, "HTTP/1.1 404 Not Found\r\n");
send_new(fd, "Server : Web Server in C\r\n\r\n");
send_new(fd, "<html><head><title>404 Not Found</head></title>");
send_new(fd, "<body><p>404 Not Found: The requested resource could not be found!</p></body></html>\r\n");
//Handling php requests
} else if (strcmp(extensions[i].ext, "php") == 0) {
php_cgi(resource, fd);
sleep(1);
close(fd);
exit(1);
} else {
printf("200 OK, Content-Type: %s\n\n",
extensions[i].mediatype);
send_new(fd, "HTTP/1.1 200 OK\r\n");
send_new(fd, "Server : Web Server in C\r\n\r\n");
if (ptr == request + 4) // if it is a GET request
{
if ((length = get_file_size(fd1)) == -1)
printf("Error in getting size !\n");
size_t total_bytes_sent = 0;
ssize_t bytes_sent;
while (total_bytes_sent < length) {
//Zero copy optimization
if ((bytes_sent = sendfile(fd, fd1, 0,
length - total_bytes_sent)) <= 0) {
if (errno == EINTR || errno == EAGAIN) {
continue;
}
perror("sendfile");
return -1;
}
total_bytes_sent += bytes_sent;
}
//why is it not appearing up to 11:30
}
}
break;
}
int size = sizeof(extensions) / sizeof(extensions[0]);
if (i == size - 2) {
printf("415 Unsupported Media Type\n");
send_new(fd, "HTTP/1.1 415 Unsupported Media Type\r\n");
send_new(fd, "Server : Web Server in C\r\n\r\n");
send_new(fd, "<html><head><title>415 Unsupported Media Type</head></title>");
send_new(fd, "<body><p>415 Unsupported Media Type!</p></body></html>");
}
}
close(fd);
}
}
shutdown(fd, SHUT_RDWR);
}
int main(int argc, char *argv[]) {
int sockfd, newsockfd, portno, pid;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
if (argc < 2) {
fprintf(stderr, "ERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd, 5);
clilen = sizeof(cli_addr);
/*
Server runs forever, forking off a separate
process for each connection.
*/
while (1) {
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
pid = fork();
if (pid < 0)
error("ERROR on fork");
if (pid == 0) {
close(sockfd);
connection(newsockfd);
exit(0);
} else
close(newsockfd);
} /* end of while */
close(sockfd);
return 0; /* we never get here */
}
NOTE: the kill.txt contains the directory of the server, the files(jpegs, gifs, etc.: /home/user/Desktop)
PROBLEM:
1. After I compile the program and execute it on my web browser as "localhost:port number/file" this is what appears on my web browser:
the image "http://localhost.... cannot be displayed because it contains errors.
And this is what appears on my terminal:
GET /sample5.gif HTTP/1.1
Opening "/home/user/Desktop/sample5.gif"
200 OK, Content-Type: image/gif
GET /favicon.ico HTTP/1.1
Opening "/home/user/Desktop/favicon.ico"
404 File not found Error
How do I fix this? Any help/comment would be greatly appreciated! Thanks.
Where is that favicon.ico bit coming from? /I looked this up and apparently having that favicon.ico bit is quite normal (can somebody please confirm this?)/
… I stumbled upon this amazing code from …
It is indeed amazing how bad it is.
At the end of the function int connection(int fd) there's:
close(fd);
}
}
shutdown(fd, SHUT_RDWR);
}
Browsers don't like the connection being reset by peer (due to close()) before it's tidily shut down. Move the close() after the shutdown().
The program neglects to reap child processes, thus a zombie process remains after each request. #include <signal.h> and add sigignore(SIGCHLD); at the start of main().
If the action for the SIGCHLD signal is set to SIG_IGN, child
processes of the calling processes will not be transformed into zombie
processes when they terminate.

How do I make cout stop outputting text after the page is full?

I've made a simple web browser using winsock2 and I have it cout the response from the server but it sends sum 21000 bytes and I need to be able to copy and paste the html, javascript, css, etc for testing the gui I made. It always fills up the terminal and I can't see where it starts I just end up in the middle of a lot of javascript. I want it to be like in the cmd where it stops and ask if you want to continue.
#include <windows.h>
#include <winsock2.h>
#include <conio.h>
#include <stdio.h>
#include <iostream>
using namespace std;
#define SCK_VERSION2 0x0202
#define DEFAULT_BUFLEN 21000
#define DEFAULT_PORT 27015
namespace Globals{
string input = "";
char recvbuf[DEFAULT_BUFLEN];
const char* carf = recvbuf;
}
using namespace Globals;
HWND staticText2 = CreateWindowEx(WS_EX_PALETTEWINDOW, TEXT("Static"), TEXT("Email"), /* email */
WS_CHILD | WS_VISIBLE, 122, 80, 44, 20,
/*hwnd*/NULL, NULL, NULL, NULL);
int sck() {
//----------------------
// Declare and initialize variables.
WSADATA wsaData;
int iResult;
SOCKET ConnectSocket = INVALID_SOCKET;
struct sockaddr_in clientService;
char name[500] = "";
char ipADDRESS[500] = "";
char sPORT[500] = "";
sockaddr_in sName;
int sNameSize = sizeof(sName);
char const* sendbuf = "GET /?gws_rd=ssl HTTP/1.1\r\n"
"Host: www.google.com:80\r\n"
"User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)\r\n"
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
"Accept-Language: en-us,en;q=0.5\r\n"
//"Accept-Encoding: gzip,deflate\r\n"
"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
"Keep-Alive: 300\r\n"
"Connection: keep-alive\r\n"
"Pragma: no-cache\r\n"
"DNT: 1"
"Cookie:
"Cookie:
"Cache-Control: no-cache\r\n\r\n";
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN; //23.214.132.132 GoDaddy.com
int WSAERROR = WSAGetLastError(); //190.93.243.15
//system("color 04"); //172.16.100.114 Mrs.Hall
//----------------------
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR) {
printf("WSAStartup failed: %d\n", iResult);
return 1;
}
//----------------------
// Create a SOCKET for connecting to server
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET) {
printf("Error at socket(): %i\n", WSAGetLastError() );
WSACleanup();
return 1;
}
//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port of the server to be connected to.
printf("IP ADDRESS: 74.125.196.191 is Google 216.58.208.37 is mail.google.com 129.66.24.10 is iNow\n");
cin >> ipADDRESS;
printf("PORT: \n");
cin >> sPORT;
//system("color 04");
u_short PORT = strtoul(sPORT, NULL, 0);
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr(ipADDRESS); //74.125.196.191
clientService.sin_port = htons(PORT); //135: msrpc, 445: microsoft-ds, 554: rtsp, 1025: NFS-or-IIS, 1026: LSA-or-nterm
//1027: IIS, 1028: uknown, 1029: ms-lsa, 139: weird behavior
//----------------------
// Connect to server.
iResult = connect( ConnectSocket, (SOCKADDR*) &clientService, sizeof(clientService) );
if ( iResult == SOCKET_ERROR) {
closesocket (ConnectSocket);
printf("Unable to connect to server: %i\n", WSAGetLastError());
WSACleanup();
return 1;
}
//----------------------
//Get local host name
iResult = gethostname(name, sizeof(name));
if (iResult == NO_ERROR) {
printf("Host Name: %s\n", name);
}
else if (iResult == SOCKET_ERROR) {
printf("Could not resolve host name: %i", WSAGetLastError());
}
//------------------------
//Get peer name
iResult = getpeername(ConnectSocket, (struct sockaddr*)&sName, &sNameSize);
if (iResult == NO_ERROR)
printf("Peer Name: %s\n", inet_ntoa(sName.sin_addr));
else if (iResult == SOCKET_ERROR)
printf("Could not get peer name: %i\n", WSAGetLastError());
//-------------------------
// Send an initial buffer
iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
if (iResult == SOCKET_ERROR) {
printf("send failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
else
printf("Bytes Sent: %i\n", iResult);
//-----------------------------
// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// Receive until the peer closes the connection
do {
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if ( iResult > 0 ) {
printf("Bytes received: %d\n", iResult);
cout << "From Server" << recvbuf << endl;//printf("From server: %s\n", recvbuf);
}
else if ( iResult == 0 )
printf("Connection closed\n");
else if (WSAERROR == WSAETIMEDOUT)
printf("recv failed: WSAETIMEDOUT\n");
} while( iResult > 0 );
// cleanup
closesocket(ConnectSocket);
WSACleanup();
system("PAUSE");
return 0;
}
int main() {
sck();
MessageBox(NULL, "Successful", "Result:", MB_OK);
}
That's my code
Just realized all I have to do is go to the webpage and change the cookie to what I made it in my program using the EditThisCookie plugin, then copy the source. XD

C forking stops after 5 children

I am working on a C program which makes a connection to a database, grabs a list of devices, then forks the requests and creates an SSH connection to that device. The issue I am having is that, the query, which has 700 results, is always starting from the beginning after it hits 5 forks.
Essentially, I've looked into pthread and glibc to handle threading, but some of the examples I found did not work as desired, or added too much complexity.
The problem I am having is, it will stop at 5 children, and stop, instead of finishing the rest of the 700 devices.
Example code:
#include <libssh2.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <unistd.h>
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
#include <limits.h>
#include <mysql.h>
/********************************
*
* gcc -o confmgr cfgmgr.c -Wall -lpthread -lz -lm -lrt -ldl -lssh2 $(mysql_config --cflags) $(mysql_config --libs) -std=gnu99
*
********************************/
static int waitsocket(int socket_fd, LIBSSH2_SESSION *session)
{
struct timeval timeout;
int rc;
fd_set fd;
fd_set *writefd = NULL;
fd_set *readfd = NULL;
int dir;
timeout.tv_sec = 10;
timeout.tv_usec = 0;
FD_ZERO(&fd);
FD_SET(socket_fd, &fd);
/* now make sure we wait in the correct direction */
dir = libssh2_session_block_directions(session);
if(dir & LIBSSH2_SESSION_BLOCK_INBOUND)
readfd = &fd;
if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
writefd = &fd;
rc = select(socket_fd + 1, readfd, writefd, NULL, &timeout);
return rc;
}
int *connect_to_device(MYSQL_RES** args){
printf("%s", args[2]);
const char *hostname = "1.1.1.1";
const char *commandline = "command_to_run ";
const char *username = "static_user";
const char *password = "static_pass";
unsigned long hostaddr;
int sock;
struct sockaddr_in sin;
const char *fingerprint;
LIBSSH2_SESSION *session;
LIBSSH2_CHANNEL *channel;
int rc;
int exitcode;
char *exitsignal=(char *)"none";
int bytecount = 0;
size_t len;
LIBSSH2_KNOWNHOSTS *nh;
int type;
rc = libssh2_init (0);
if (rc != 0) {
fprintf (stderr, "libssh2 initialization failed (%d)\n", rc);
return 1;
}
hostaddr = inet_addr(hostname);
/* Ultra basic "connect to port 22 on localhost"
* Your code is responsible for creating the socket establishing the
* connection
*/
sock = socket(AF_INET, SOCK_STREAM, 0);
sin.sin_family = AF_INET;
sin.sin_port = htons(22);
sin.sin_addr.s_addr = hostaddr;
if (connect(sock, (struct sockaddr*)(&sin),
sizeof(struct sockaddr_in)) != 0) {
fprintf(stderr, "failed to connect!\n");
return -1;
}
/* Create a session instance */
session = libssh2_session_init();
if (!session)
return -1;
/* tell libssh2 we want it all done non-blocking */
libssh2_session_set_blocking(session, 0);
/* ... start it up. This will trade welcome banners, exchange keys,
* and setup crypto, compression, and MAC layers
*/
while ((rc = libssh2_session_handshake(session, sock)) ==
LIBSSH2_ERROR_EAGAIN);
if (rc) {
fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
return -1;
}
/* We could authenticate via password */
while ((rc = libssh2_userauth_password(session, username, password)) == LIBSSH2_ERROR_EAGAIN);
if (rc) {
fprintf(stderr, "Authentication by password failed.\n");
goto shutdown;
}
libssh2_trace(session, LIBSSH2_TRACE_TRANS | LIBSSH2_TRACE_KEX | LIBSSH2_TRACE_AUTH | LIBSSH2_TRACE_CONN | LIBSSH2_TRACE_SCP | LIBSSH2_TRACE_SFTP | LIBSSH2_TRACE_ERROR | LIBSSH2_TRACE_PUBLICKEY );
/* Exec non-blocking on the remove host */
while( (channel = libssh2_channel_open_session(session)) == NULL &&
libssh2_session_last_error(session,NULL,NULL,0) == LIBSSH2_ERROR_EAGAIN )
{
waitsocket(sock, session);
}
if( channel == NULL )
{
fprintf(stderr,"Error\n");
exit( 1 );
}
while( (rc = libssh2_channel_exec(channel, commandline)) == LIBSSH2_ERROR_EAGAIN )
{
waitsocket(sock, session);
}
if( rc != 0 )
{
fprintf(stderr,"Error\n");
exit( 1 );
}
for( ;; )
{
// loop until we block
int rc;
do
{
char buffer[0x4000];
/* strange thing */
sleep( 1 );
rc = libssh2_channel_read( channel, buffer, sizeof(buffer) );
if( rc > 0 )
{
int i;
for( i=0; i < rc; ++i )
putchar( buffer[i] );
}
}
while( rc > 0 );
// this is due to blocking that would occur otherwise so we loop on this condition
if( rc == LIBSSH2_ERROR_EAGAIN )
{
waitsocket(sock, session);
}
else if( rc == 0 )
break;
}
while( (rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN )
;
if( rc == 0 )
{
//does-not-work if( libssh2_channel_wait_closed(channel) == 0 )
exitcode = libssh2_channel_get_exit_status( channel );
}
printf("\n%d\n", 221 );
libssh2_channel_free(channel);
channel = NULL;
/***********************/
shutdown:
libssh2_session_disconnect(session, "Normal Shutdown, Thank you for playing");
libssh2_session_free(session);
close(sock);
fprintf(stderr, "\n----------------------\nScript Finished\n\n");
libssh2_exit();
return 7;
}
/********************************
*
*
*
*
********************************/
int main(int argc, char *argv[]){
pid_t childPID;
int children = 0;
MYSQL *conn;
MYSQL_RES *res;
MYSQL_ROW row;
char *mySQLserver = "localhost";
char *mySQLuser = "root";
char *mySQLpassword = ""; /* set me first */
char *mySQLdatabase = "Devices";
conn = mysql_init(NULL);
/* Connect to database */
if (!mysql_real_connect(conn, mySQLserver,
mySQLuser, mySQLpassword, mySQLdatabase, 0, NULL, 0)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
/* send SQL query */
if (mysql_query(conn, "SELECT Hostname,Descr,IP,Username,Password FROM All_Active_Devices")) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
res = mysql_use_result(conn);
/* output table name */
printf("MySQL Tables in mysql database:\n");
while ((row = mysql_fetch_row(res)) != NULL){
printf("%s \n", row[0]);
children++; // Last fork() was successful
while (children >= 5)
{
int status;
// Wait for one child to exit
if (wait(&status) == 7)
{
children--;
}
}
childPID = fork ();
if (childPID < 0) {
printf("Fork Error \n");
} else if (childPID == 0) {
printf("\tCreating Fork for %s: pid %d \n", row[0], childPID);
connect_to_device ( &row );
}
else{
printf("\tDid not create Fork for %s \n", row[0]);
}
}
/* close connection */
mysql_free_result(res);
mysql_close(conn);
return 0;
}
Your child processes are exitting - in particular not with exit status 7 - you have a return in your connect_to_device function, but that is ignored, and each child starts going round the loop, creating more children.
You probably want: return connect_to_device ( &row ); instead.
wait() returns the child PID that died, not its status - which is in WEXITSTATUS(status).
What happens after connect_to_device returns? It looks like that thread will also start in on the while loop as I don't see that child process exiting, sitting you in the while children >=5 loop. The 5 in your condition and 5 threads isn't a coincidence.
Some output from a run would be helpful, also paring down the code.
Try to get your scaffolding working, without the ssh code. Just getting the processes to stop and start shouldn't need ssh. Then add in the application logic once you're sure the underlying support works.
Perhaps ServerAliveCountMax is getting in the way:
EDIT FROM NETCODER BELOW
ServerAliveCountMax
Sets the number of server alive messages (see
below) which may be sent without ssh(1) receiving any messages back
from the server. If this threshold is reached while server alive
messages are being sent, ssh will disconnect from the server,
terminating the session. It is important to note that the use of
server alive messages is very different from TCPKeepAlive (below). The
server alive messages are sent through the encrypted channel and
therefore will not be spoofable. The TCP keepalive option enabled by
TCPKeepAlive is spoofable. The server alive mechanism is valuable when
the client or server depend on knowing when a connection has become
inactive.
The default value is 3. If, for example, ServerAliveInterval (see
below) is set to 15 and ServerAliveCountMax is left at the default, if
the server becomes unresponsive, ssh will disconnect after
approximately 45 seconds. This option applies to protocol version 2
only.
See the man page for ssh_config (man 5 ssh_config) for details.