How to create a simple Proxy to access web servers in C - c

I’m trying to create an small Web Proxy in C. First, I’m trying to get a webpage, sending a GET frame to the server.
I don’t know what I have missed, but I am not receiving any response. I would really appreciate if you can help me to find what is missing in this code.
int main (int argc, char** argv) {
int cache_size, //size of the cache in KiB
port,
port_google = 80,
dir,
mySocket,
socket_google;
char google[] = "www.google.es", ip[16];
struct sockaddr_in socketAddr;
char buffer[10000000];
if (GetParameters(argc,argv,&cache_size,&port) != 0)
return -1;
GetIP (google, ip);
printf("ip2 = %s\n",ip);
dir = inet_addr (ip);
printf("ip3 = %i\n",dir);
/* Creation of a socket with Google */
socket_google = conectClient (port_google, dir, &socketAddr);
if (socket_google < 0) return -1;
else printf("Socket created\n");
sprintf(buffer,"GET /index.html HTTP/1.1\r\n\r\n");
if (write(socket_google, (void*)buffer, MESSAGE_LENGTH+1) < 0 )
return 1;
else printf("GET frame sent\n");
strcpy(buffer,"\n");
read(socket_google, buffer, sizeof(buffer));
// strcpy(message,buffer);
printf("%s\n", buffer);
return 0;
}
And this is the code I use to create the socket. I think this part is OK, but I copy it just in case.
int conectClient (int puerto, int direccion, struct sockaddr_in *socketAddr) {
int mySocket;
char error[1000];
if ( (mySocket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
printf("Error when creating the socket\n");
return -2;
}
socketAddr->sin_family = AF_INET;
socketAddr->sin_addr.s_addr = direccion;
socketAddr->sin_port = htons(puerto);
if (connect (mySocket, (struct sockaddr *)socketAddr,sizeof (*socketAddr)) == -1) {
snprintf(error, sizeof(error), "Error in %s:%d\n", __FILE__, __LINE__);
perror(error);
printf("%s\n",error);
printf ("-- Error when stablishing a connection\n");
return -1;
}
return mySocket;
}
Thanks!

First, you're not checking how many bytes the write(2) call actually wrote to the socket. The return value of the call tells you that. Same for the read(2). TCP socket is a bi-directional stream, so as a rule always do both in a loop until expected number of bytes is transferred, EOF is read (zero return from read(2)), or an error occurred (which you are not checking for when reading either).
Then HTTP is rather complex protocol. Make yourself familiar with RFC 2616, especially application level connection management and transfer encodings.
Edit 0:
Hmm, there's no such thing as "simple" proxy. You need to manage multiple connections (at least client-to-proxy and proxy-to-server), so it's probably best to look into select(2)/poll(2)/epoll(4)/kqueue(2) family of system call, which allow you to multiplex I/O. This is usually combined with non-blocking sockets. Look into helper libraries like libevent. Look at how this is done in good web-servers/proxies like nginx. Sound like it's a lot for you to discover, but don't worry, it's fun :)

Since you didn't post the GetIP routine, I am not certain that your hostname lookup is correct, as from the looks of it, I am not sure that you are using inet_addr function correctly.
Nikolai has pointed out some very good points (and I fully agree). In fact you GET request is actually broken, and while I was testing it on my own local Apache web server on my system, it didn't work.
sprintf(buffer,"GET /index.html HTTP/1.1\r\n\r\n");
if (write(socket_google, (void*)buffer, LONGITUD_MSJ+1) < 0 )
return 1;
else printf("GET frame sent\n");
...
strcpy(buffer,"\n");
read(socket_google, buffer, sizeof(buffer));
should be replaced with
snprintf(buffer, sizeof(buffer),
"GET / HTTP/1.1\r\nHost: %s\r\nUser-Agent: TEST 0.1\r\n\r\n",
google);
if (write(socket_google, buffer, strlen(buffer)+1) < 0 ) {
close(socket_google);
return 1;
} else
printf("GET frame sent\n");
...
buffer[0] = '\0';
/* Read message from socket */
bytes_recv = read(socket_google, buffer, sizeof(buffer));
if (bytes_recv < 0) {
fprintf(stderr, "socket read error: %s\n", strerror(errno));
close(socket_google);
exit(10);
}
buffer[bytes_recv] = '\0'; /* NUL character */
/* strcpy(message,buffer); */
printf("%s\n", buffer);
...
You should also close the socket before exiting the program. Enable standard C89/90 or C99 mode of your compiler (e.g. -std=c99 for gcc) and enable warnings (e.g. -Wall for gcc), and read them. And #include the necessary header files (assuming Linux in my case) for function prototypes:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h> /* for gethostbyname() */
There is some casting of pointers and structs in regards to the hostname / IP address resolving, which can be confusing and easy place to make a mistake, so verify that is working as you expect it is.
in_addr_t ip;
...
GetIP(google, &ip); /* I changed the parameters */
printf("IP address = %x (%s)\n",
ip,
inet_ntoa(*((struct in_addr*)&ip)));

Actually, I've been implementing a small web proxy using my library called rzsocket link to it.
One of the most difficult things I've found when implementing the web proxy, perhaps this might also be your problem, was that, in order to make the proxy work properly, I had to set keep-alive settings false. One way of doing this in FireFox, is accessing about:config address, and setting the value of network.http.proxy.keep-alive to false.

Related

Bluetooth on the EV3

Before I get started. Yes, I could use leJOS, ev3dev, or some others, but I'd like to do it this way because that is how I learn.
I am using the CodeSourcery arm-2009q1 arm toolchain. I fetched the required libraries (bluetooth) from here: https://github.com/mindboards/ev3sources.
I am uploading the programs to the brick by using this tool: https://github.com/c4ev3/ev3duder
I have also fetched the brick's shared libraries, but I can not get them to work properly and there is 0 documentation on how to write a c program for the ev3 using the shared libraries. If I could get that working I might be able to use the c_com module to handle bluetooth, but right now bluez and rfcomm in conjunction with: https://github.com/c4ev3/EV3-API for motor and sensor control seems to be my best bet.
Now, with that out of the way:
I'd like to run the EV3 as a bluetooth "server" meaning that I start a program on it and the program opens a socket, binds it, listens for a connection, and then accepts a single connection.
I am able to do open a socket, bind it to anything but channel 1 (I believe this might be the crux of my issue), I am able to listen. These all return 0 (OK) and everything is fine.
Then I try to accept a connection. That instantly returns -1 and sets the remote to address 00:00:00:00:00:00.
My code is pretty much the same as can be found here: https://people.csail.mit.edu/albert/bluez-intro/x502.html
Here it is:
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
#include <ev3.h>
int main(int argc, char **argv)
{
InitEV3();
struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
char buf[1024] = { 0 };
int sock, client, bytes_read;
socklen_t opt = sizeof(rem_addr);
sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
loc_addr.rc_family = AF_BLUETOOTH;
loc_addr.rc_bdaddr = *BDADDR_ANY;
loc_addr.rc_channel = 2; // <-- Anything but 1. 1 seems to be taken
bind(sock, (struct sockaddr *)&loc_addr, sizeof(loc_addr));
listen(sock, 1);
// accept one connection <-- PROGRAM FAILS HERE AS accept() returns -1
client = accept(sock, (struct sockaddr *)&rem_addr, &opt);
// ---- All following code is irrelevant because accept fails ----
ba2str( &rem_addr.rc_bdaddr, buf );
fprintf(stderr, "accepted connection from %s\n", buf);
memset(buf, 0, sizeof(buf));
bytes_read = read(client, buf, sizeof(buf));
if( bytes_read > 0 )
printf("received [%s]\n", buf);
close(client);
close(sock);
FreeEV3();
return 0;
}
I am able to get the same code working on my pi. Even communication back and forth when the ev3api-specific functions are commented out. I just can't fathom why it won't work on the EV3.
I figured it out.
On my raspberry PI, the accept call worked as expected with no quirks. On the EV3 however, the accept call is non-blocking even if it has not been told to act like so.
The solution was to place the accept call in a loop until an incoming connection was in the queue.
while (errno == EAGAIN && ButtonIsUp(BTNEXIT) && client < 0)
client = accept(sock, (struct sockaddr*)&rem_addr, sizeof(rem_addr));
I'll upload the code to github. Contact me if you'd like to do something similar with the EV3.

C http proxy server socket - not hitting

I am trying to understand HTTP proxy server program. I wrote a simple C based socket which sends a response to as Message received. Please find the program below.
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/types.h>
int main(){
int recvSocketFd = 0;
struct sockaddr_in serv_input_addr;
char inputBuff[1024];
memset(&serv_input_addr,'0',sizeof(serv_input_addr));
memset(&inputBuff, '0', sizeof(inputBuff));
recvSocketFd = socket(AF_INET,SOCK_STREAM,0);
if(recvSocketFd <= 0){
printf("\nError occurred while creating a socket\n");
return -1;
}
serv_input_addr.sin_family = AF_INET;
serv_input_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_input_addr.sin_port = htons(8080);
bind(recvSocketFd, (struct sockaddr*)&serv_input_addr, sizeof(serv_input_addr));
listen(recvSocketFd,5);
int connFd = 0;
int n = 0;
int client_length = sizeof(serv_input_addr);
while(1){
connFd = accept(recvSocketFd, (struct sockaddr*)&serv_input_addr, &client_length);
if(connFd <0){
printf("\nError in accepting messages from socket\n");
return -1;
}
n = read(connFd,inputBuff,1023);
if(n>0){
printf("\nMessage : %s\n",inputBuff);
}
write(connFd,"Message received",15);
close(connFd);
}
}
This program on running is responding properly for the below request http://<localhost>:8080/test.
I tried to set this as a proxy. So I tried to set this as manual proxy in Firefox as http://<localhost> and port as 8080.
But the request is not hitting this socket.
It would be really helpful if somebody could help me in understanding this.
Note: This is not a homework program and I am not a student. I am just trying to learn things. This statement is for our honorable disgraceful respondents.
Re-Edit:
Note the importance of checking success on bind(). There is various cases; where one could be that the socket is in a TIME_WAIT state. If one does not actually validate the bind() and abort on failure the program could possibly seemingly be running OK. listen() can be passed without error. Though on the client side Firefox most likely would report with a refused connection it is not a given.
URI-scheme-name
In your question you state that you have used http://<localhost> for proxy settings. If that is literal it will fail: You are not to include the scheme name in the proxy settings.
Note that Firefox does not validate the hostname. E.g. a4a6®←#ł´ªĸµª5d4a"#¤&%=)(=/)= fly by with no warnings.
If one include the scheme, http://, Firefox will fail to connect and one will get Server not found.
Original answer :-)
I'll leave it here even with comment on removed parts, as someone else might find it useful. (And that I used some time on writing it up.)
There are some issues here. I'll take them one by one.
First fix this, then report back if you want.
Missing header files and wrong types
read(), write() and close() are defined in <unistd.h>, but you do not include this file. It is presumably linked in, but best to add.
client_length is not signed int. You can use unsigned int, but best to use socklen_t as is defined in manual.
read() returns ssize_t, not int. Change this one as well.
Lack of error checking
No error checking where it should be. Rule #1: Always check for errors! Having trouble and not validating requests is … a big no no.
bind(), listen() and close() return int. 0 is success, -1 is error. On error errno is set.
The manual is very clear and easy to read on this. Read it for each function you use.
Include <errno.h> and use perror().
In simplest way. Aborting and no attempt to rescue we get:
int res;
...
res = bind(recvSocketFd, (struct sockaddr*)&serv_input_addr, sizeof(serv_input_addr));
if (res != 0) {
perror("bind");
return errno;
}
res = listen(recvSocketFd, 5);
if (res != 0) {
perror("listen");
return errno;
}
...
res = close(connFd);
if (res != 0) {
perror("close");
return errno;
}
write() returns ssize_t which on success is how many bytes was written, else -1 and errno set appropriately.
res_wr = write(connFd, ...);
if (res == -1) {
perror("write");
return errno;
}
/* Else check if entire buffer was written, if not, act accordingly. */
Write statement
Bad write statement:
write(connFd, "Message received", 15);
First: "Message received" is 17 bytes including terminating null. If you want to write this to connection use something like:
const char msg_received[] = "Message received";
...
write(connFd, msg_received, sizeof(msg_received));
Second: This is what you pass on to the client, in your case Firefox. Firefox would in other words get the characters:
{ 'M', 'e', 's', 's', 'a', 'g', 'e', ' ', 'r', 'e', 'c', 'e', 'i', 'v', 'e' }
Third: As you promptly do a close() after first read/write. Firefox will most likely reply with a The connection was reset. Normally you would write your inputBuff, and not some status message like this.
Print to stderr
As a side not: Whilst it is fair enough to write to stdout in this sample, it is a good habit to write errors and debugging data to stderr. Keep it as a habit. Example:
sz_buf = read(connFd, inputBuff, BUF_SIZE - 1)
inputBuff[sz_buf] = 0x00;
fprintf(stderr,
"\n====================== Message (%4d) ================\n"
"%s\n"
"--------------------------------------------------------\n"
,
sz_buf, inputBuff
);

Windows Socket Programming in C

I am taking a networking class where the Professor is literally reading the book to the class. Needless to say I have no Idea what I am doing. Our semester project is to copy code from our text book and make a client-server network. Literally copying the code from teh book with no modifications.
The book had mistakes in the code (missing semicolons, extra paranthesis) but I managed to at least compile the code. However, I run into a bunch of link errors.
Example:
Error 1 error LNK2019: unresolved external symbol impsendto#24 referenced in function _main C:\Users\Documents\Visual Studio 2010\Projects\Client_Server\Client_Server\Client_Server\Server.obj Client_Server
i looked up the error code and I think the code is trying to link to definitions that are not existent in the header files. I have a tough time fixing LNK errors vs Syntax errors. But like I said I have no idea how to go about fixing this. I am sending the code for the server side, I ran into the same errors on the client side.
include <stdio.h>
include <string.h>
include <WinSock2.h>
include <WinSock.h>
include <stdint.h>
include <time.h>
int main(void) {
int s;
int len;
char buffer[256];
struct sockaddr_in servAddr;
struct sockaddr_in clntAddr;
int clntAddrLen; //length of client socket addre
//Build local (server) socket add
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(21);
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
//create socket
if((s=socket(PF_INET, SOCK_DGRAM, 0) <0 ))
{
perror("Error: Socket Failed!");
exit(1);
}
//bind socket to local address and port
if((bind(s,(struct sockaddr*)&servAddr, sizeof(servAddr))<0))
{
perror("Error:bind failed!");
exit(1);
}
for(;;)
{
len = recvfrom(s,buffer, sizeof(buffer),0,(struct sockaddr*)&clntAddr, &clntAddrLen);
//send string
sendto(s, buffer, len, 0, (struct sockaddr*)&clntAddr, sizeof(clntAddr));
}
}
Any tips, links to useful info, or advice would be appreciated. I tried reading the text book but I am completely lost. Also, this is the only code related assignment we have done all semester. Everything else has been collecting packets using a packet sniffer. Literally came into class and said copy and run code on page X.
You need to link the library Ws2_32.lib to use winsock. You also must call WSAStartup before using any other winsock functions (this isn't causing your current error, but will cause you problems once you fix the missing library issue).
At first I will try to help using your last comment: Let us assume you are using Visual Studio (I think it is best option to start winsock for windows programming as Microsoft cares about Windows basic libraries being up to date and they are compatible with helpful msdn support).
If you are getting error such as this one:
1>asdf.obj : error LNK2001: unresolved external symbol _imp_WSAStartup#8
it means that ws2_32.lib is not linked correctly. To do that right click on your project in solution explorer, go to linker -> input and add ws2_32.lib to additional dependencies. This library is part of windows SDK (I guess it is installed together with most versions of Visual Studio), so make sure the file exists on your computer.
And now how to make correct project in modern style without following ancient tutorials:
The library you need to add is Winsock2.h. Winsock.h is old (deprecated) version and there is no need to use it in new applications. To start using sockets you need to call function WSAStartup, to do that you must initialize struct WSADATA at the beginning.
The basic piece of code looks like this:
#include <Winsock2.h>
int main()
{
WSADATA mywsadata; //your wsadata struct, it will be filled by WSAStartup
WSAStartup(0x0202,&mywsadata); //0x0202 refers to version of sockets we want to use.
//here goes your code with socket related things
return 0;
}
For more help you can visit here
A note: since question is old and I am not sure its author will ever find my answer helpful I want to help another users looking at this question
The following is a simple socket program (simple http client) that will run on both Windows and Linux. If you are using "gcc on windows" then you need to compile using the following command:
gcc prog_name.c -lws2_32
Code:
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#if defined(_WIN32) || defined(_WIN64)
#include <winsock2.h>
#else
#include <sys/socket.h>
#include <arpa/inet.h>
#endif
#define MSG_SIZE 1024
#define REPLY_SIZE 65536
int main(int argc, char *argv[])
{
int s = -1;
struct sockaddr_in server;
char message[MSG_SIZE] = {0}, server_reply[REPLY_SIZE] = {0};
int recv_size = 0;
#if defined(_WIN32) || defined(_WIN64)
WSADATA wsa;
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0) {
printf("\nError: Windows socket subsytsem could not be initialized. Error Code: %d. Exiting..\n", WSAGetLastError());
exit(1);
}
#endif
//Create a socket
if((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("Error: Could not create socket: %s. Exiting..\n", strerror(errno));
exit(1);
}
// Fill in server's address
memset(&server, 0, sizeof(server));
server.sin_addr.s_addr = inet_addr("172.217.160.238"); // google.com
server.sin_family = AF_INET;
server.sin_port = htons(80);
// Connect to server
if (connect(s, (struct sockaddr *)(&server), sizeof(server)) < 0) {
printf("Error: Could not connect to server: %s. Exiting..\n", strerror(errno));
exit(1);
}
// Send HTTP request
strcpy(message, "GET / HTTP/1.1\r\n\r\n");
if(send(s, message, strlen(message), 0) < 0) {
printf("Error: Could not send http request to server: %s. Exiting..\n", strerror(errno));
exit(1);
}
// Receive a reply from the server
printf("\nWaiting for server reply..\n");
if((recv_size = recv(s, server_reply, REPLY_SIZE, 0)) < 0) {
printf("Error: Something wrong happened while getting reply from server: %s. Exiting..\n", strerror(errno));
exit(1);
}
server_reply[REPLY_SIZE - 1] = 0;
printf("\nServer Reply:\n\n");
printf("%s\n", server_reply);
// Close the socket
#if defined(_WIN32) || defined(_WIN64)
closesocket(s);
WSACleanup();
#else
close(s);
#endif
exit(0);
} // end of main

With C TCP sockets, can 'send' return zero?

Is it ever possible for the C send function to return zero when using TCP sockets? The man page just says that it will return the number of bytes sent, but I am not sure if it will just return -1 when it can't send any data.
I'm pretty certain, though the memory is deep in the mists of time, that I've seen it return zero before, in the situation of massive data transfers where the other end was not keeping up.
From memory, in that case, the remote TCP stack buffers had filled up, the stack had notified the local end that it was to delay until some space was cleared out and the local buffers had filled up as well.
At that point, it's not technically an error (hence no -1 returned) but no data could be accepted by the local stack.
I'm not entirely certain that's the case now since the current Posix standard seems to indicate it will simply block in that case (or fail if it's set up for non-blocking).
However, I suspect it's a moot point. You do have the possibility that it will return less than the bytes you requested to send and you therefore should have code in place to handle that.
And, since it will be pretty much the same logic handling 'one less than what you requested' as handling 'zero bytes', you may as well assume it can return zero.
Well, there is always the case where you passed in zero as the number of bytes to send... in that case, "returning the number of bytes sent" would indicate that it should return zero bytes.
Probably best to handle the returns-zero case properly anyway; it can't hurt, and it might help.
The answer to this may well be implementation dependent and therefore vary based on the operating system.
One circumstance where 0 would be expected, when you request a transmission of 0 bytes.
The BSD man page states:
If no messages space is available at the socket to hold the message to be transmitted, then send() normally blocks, unless the socket has been placed in non-blocking I/O mode.
The Posix specification goes further and states that in blocking mode all data is transferred, unless an interrupt occurs.
In both cases zero cannot be returned unless the count supplied was zero.
I do observe a zero return from the send(2) on an AF_UNIX type socket right now.
Yepp, it was due to the size field of zero value.
So, JFYI.
send returns 0 when you send(socket, buf, 0, 0)
I'd like to provide simple code for others to test.
Server:
In one terminal:
nc -l localhost 10086
Client:
In another terminal:
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
int create_socket()
{
addrinfo hints = {};
addrinfo* servinfo;
int sockfd = -1;
int rv;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = 0;
if ((rv = getaddrinfo("localhost", "10086", &hints, &servinfo)))
{
printf("getaddrinfo failed: %s\n", gai_strerror(rv));
exit(1);
}
for(auto p = servinfo; p; p = p->ai_next)
{
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
{
perror("socket");
continue;
}
else
{
if(connect(sockfd, p->ai_addr, p->ai_addrlen) == -1)
{
close(sockfd);
perror("connect");
continue;
}
else
puts("client: connected");
}
break;
}
freeaddrinfo(servinfo);
return sockfd;
}
void client()
{
int socket = create_socket();
if(socket == -1)
{
puts("no good");
exit(1);
}
char buf[100] = {0};
while(1){
int ret = send(socket, buf, 0, 0);
if (ret == 0){
printf(".");
}else{
printf("xxxxxxx\n");
}
}
}
int main()
{
setvbuf(stdout, NULL, _IONBF, 0);
client();
return 0;
}
g++ -g -Wall -o send_zero_bytes send_zero_bytes.cpp
./send_zero_bytes

Invoke web page from Linux C

I need to read all the HTML text from a url like http://localhost/index.html into a string in C.
I know that if i put on telnet -> telnet www.google.com 80 Get webpage.... it returns all the html.
How do I do this in a linux environment with C?
I would suggest using a couple of libraries, which are commonly available on most Linux distributions:
libcurl and libxml2
libcurl provides a comprehensive suite of http features, and libxml2 provides a module for parsing html, called HTMLParser
Hope that points you in the right direction
Below is a rough outline of code (i.e. not much error checking and I haven't tried to compile it) to get your started, but use http://www.tenouk.com/cnlinuxsockettutorials.html to learn socket programming. Lookup gethostbyname if you need to translate a hostname (like google.com) into an IP address. Also you may need to do some work to parse out the content length from the HTTP response and then make sure you keep calling recv until you've gotten all the bytes.
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <stdlib.h>
void getWebpage(char *buffer, int bufsize, char *ipaddress)
{
int sockfd;
struct sockaddr_in destAddr;
if((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1){
fprintf(stderr, "Error opening client socket\n");
close(sockfd);
return;
}
destAddr.sin_family = PF_INET;
destAddr.sin_port = htons(80); // HTTP port is 80
destAddr.sin_addr.s_addr = inet_addr(ipaddress); // Get int representation of IP
memset(&(destAddr.sin_zero), 0, 8);
if(connect(sockfd, (struct sockaddr *)&destAddr, sizeof(struct sockaddr)) == -1){
fprintf(stderr, "Error with client connecting to server\n");
close(sockfd);
return;
}
// Send http request
char *httprequest = "GET / HTTP/1.0";
send(sockfd, httprequest, strlen(httprequest), 0);
recv(sockfd, buffer, bufsize, 0);
// Now buffer has the HTTP response which includes the webpage. You can either
// trim off the HTTP header, or just leave it in depending on what you are doing
// with the page
}
if you really don't feel like messing around with sockets, you could always create a named temp file, fork off a process and execvp() it to run wget -0 , and then read the input from that temp file.
although this would be a pretty lame and inefficient way to do things, it would mean you wouldn't have to mess with TCP and sending HTTP requests.
You use sockets, interrogate the web server with HTTP (where you have "http://localhost/index.html") and then parse the data which you have received.
Helpful if you are a beginner in socket programming: http://beej.us/guide/bgnet/
Assuming you know how to read a file into a string, I'd try
const char *url_contents(const char *url) {
// create w3m command and pass it to popen()
int bufsize = strlen(url) + 100;
char *buf = malloc(bufsize);
snprintf(buf, bufsize, "w3m -dump_source '%s'");
// get a file handle, read all the html from it, close, and return
FILE *html = popen(buf, "r");
const char *s = read_file_into_string(html); // you write this function
fclose(html);
return s;
}
You fork a process, but it's a lot easier to let w3m do the heavy lifting.

Resources