AWS Network Load Balancer not forwarding connection to EC2 instances - c

I am trying to establish a connection between a local client program and a server program running on an AWS EC2 instance. When I'm directly connecting through the public IP address of the EC2 instance, I face no problem and the connection is established as expected (I am printing out the IP address of the connected server to check whether the connection proceeds correctly or not)
However, when I add the EC2 instance to a Network Load Balancer and pass the NLB's IP while running the client program, then the connection that is being established is between the client program and the Load Balancer, and not the server program (as suggested by the IP address printed). I was expecting that the Load Balancer would forward the connection to the server and the connection would be established, but apparently, it's not the case
Why is it so? And how to solve this and get the desired result (i.e. the connection to be between the client and server program as it was happening without the load balancer)
EDIT: This does not seem to be a problem with load balancer configuration or permissions, as it works well when I run a simple Web Application on an Apache server on the EC2 instances (instead of the C server program). I guess the client and server programs are not establishing the connection in the desired manner. What needs to be done?
This is my client program
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <malloc.h>
#include <string.h>
#include <sys/socket.h>
#include <resolv.h>
#include <netdb.h>
#include <arpa/inet.h>
#include "openssl/ssl.h"
#include "openssl/err.h"
int OpenConnection(const char *hostname, int port) {
int sd;
struct hostent *host;
struct sockaddr_in addr;
if ( (host = gethostbyname(hostname)) == NULL )
{
printf("Could not find host\n");
perror(hostname);
abort();
}
else {
printf("Succesfully found host - %s\n", host->h_name);
}
sd = socket(PF_INET, SOCK_STREAM, 0);
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = *(long*)(host->h_addr);
if ( connect(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0 )
{
printf("Connection Failed\n");
close(sd);
perror(hostname);
abort();
}
else {
char* address = inet_ntoa(addr.sin_addr);
printf("Connection Succesful at socket %d\n", sd);
printf("%s\n", address);
printf("Port is: %d\n", ntohs(addr.sin_port));
}
return sd;
}
int main(int args, char* argv[]) {
char* hostname = argv[1];
char* port = argv[2];
int portnum = atoi(port);
int server;
server = OpenConnection(hostname, portnum);
close(server);
return 0;
}
And this is my server program
#include <errno.h>
#include <unistd.h>
#include <malloc.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <resolv.h>
#include "openssl/ssl.h"
#include "openssl/err.h"
#define FAIL -1
int OpenListener(int port) {
int sd;
struct sockaddr_in addr;
sd = socket(PF_INET, SOCK_STREAM, 0);
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY;
if (bind(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0 ) {
perror("can't bind port");
printf("Cannot bind port\n");
abort();
}
else printf("Port bind Succesful\n");
if (listen(sd, 10) != 0 ) {
perror("Can't configure listening port");
abort();
}
else printf("Configured listening port\n");
return sd;
}
int isRoot() {
if (getuid() != 0) return 0;
else return 1;
}
int main(int args, char *argv[]) {
SSL_CTX *ctx;
int server;
char *portnum;
if(!isRoot()) {
printf("This program must be run as root/sudo user!!");
exit(0);
}
if (args != 2 ) {
printf("Usage: %s <portnum>\n", argv[0]);
exit(0);
}
portnum = argv[1];
int port = atoi(portnum);
server = OpenListener(port);
while(1) {
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
int client = accept(server, (struct sockaddr*)&addr, &len);
printf("Connection: %s:%d\n",inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
}
close(server);
return 0;
}

It's hard to understand what's going on, I'll try to suggest that you need to use Application Load Balancer, because:
Network Load Balancer — this is the distribution of traffic based on network variables, such as IP address and destination ports. It is layer 4 (TCP) and below and is not designed to take into consideration anything at the application layer such as content type, cookie data, custom headers, user location, or the application behavior.

Related

C client socket does not output/connect to tcp server

Why does this header file go into a freeze state or it does not output anything even if the server is accepting connection form other scripts/tools
tcpclient.h
#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#pragma once
int socket_desc;
struct sockaddr_in server_addr;
int init_client()
{
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if (socket_desc < 0 )
{
printf("Failed to create socket\n");
return -1;
}
return 0;
}
int connection(char *host,int port )
{
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = inet_addr(host);
if (connect(socket_desc, (struct sockaddr*)&server_addr, sizeof(server_addr))<0)
{
printf("Failed to connect # %s:%d\n",host,port);
return -1;
}
printf("Connected to [%s:%d]\n",host,port);
return 0;
}
using a main.c like so
int main()
{
int soc = init_client();
int con = connection("192.168.0.12",6666);
return 0;
}
the only warning I get is that the variable soc is not used
Your program works correctly in my computer.... It's not clear what do you claim on.
Anyway, after tweaking it a bit, I have some points to comment on it. I changed the ip address to 127.0.0.1 and port to 80 and started an apache server locally to check that the server is, indeed ready to accept connections.
First I checked that the connection opened locally with a telnet(1) command (you will probably have to install it in your machine as it is not installed now by default)
$ telnet localhost 80
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
^]
telnet> close
Connection closed.
$ _
then I changed several things in your code (they should not affect the run, but they will make you trouble in the future if you don't take this path)
I first created a socket.h file to put prototypes for both functions, so you don't run in trouble if you later change the prototypes.
socket.h
#ifndef _SOCKET_H
#define _SOCKET_H
int init_client(void);
int connection(const char *host, int port);
#endif /* _SOCKET_H */
As you see, I changed the parameter `host` into a `const char *` type, so the compiler knows that the string is not changed inside the function and can optimize calls, based on that.
Second, I #included the file in both modules, so if you change the interface, both modules (provider and consumer) know about the interface change.
socket.c
#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
I used the last two includes to use strerror(errno), that gives you the reason for the connection error (mainly being a connection refused error)
#include "socket.h"
int socket_desc = -1;
struct sockaddr_in server_addr;
this is not good practice. A better solution would be to return the socket and pass it as parameter to the connection call below. Using global variables will run you into trouble later if you want to use these functions in different threads, as the socket_desc global variable is common to all the threads you will have.
int init_client(void)
{
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if (socket_desc < 0 )
{
printf("Failed to create socket, %s\n",
strerror(errno));
return -1;
}
return 0;
}
int connection(const char *host, int port)
{
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = inet_addr(host);
printf("trying connect to %s:%d\n", host, port);
if (connect(socket_desc, (struct sockaddr*) &server_addr, sizeof(server_addr))<0)
{
printf("Failed to connect # %s:%d, %s\n",
host, port, strerror(errno));
return -1;
printing here the reason of the non connection is a good idea to know what is happening.
}
printf("Connected to [%s:%d]\n",host,port);
return 0;
}
A better solution would be the following:
socket.c
#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#include "socket.h"
int init_client(void)
{
int socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if (socket_desc < 0 )
{
printf("Failed to create socket: %s\n",
strerror(errno));
}
return socket_desc;
}
int connection(int sd, const char *host, int port)
{
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = inet_addr(host);
printf("trying connect to %s:%d\n", host, port);
if (connect(sd, (struct sockaddr*) &server_addr, sizeof(server_addr)) < 0) {
printf("Failed to connect # %s:%d, %s\n",
host, port, strerror(errno));
return -1;
}
printf("Connected to [%s:%d]\n", host, port);
return 0;
}
where socket.h becomes:
socket.h
#ifndef _SOCKET_H
#define _SOCKET_H
int init_client(void);
int connection(int socket_descriptor, const char *host, int port);
#endif /* _SOCKET_H */
this modifications, made that calling the program to localhost:80 resulted in:
$ a.out
trying connect to 127.0.0.1:80
Connected to [127.0.0.1:80]
$ _
while using 79 as the port resulted in:
$ a.out
trying connect to 127.0.0.1:79
Failed to connect # 127.0.0.1:79, Connection refused
Failed connection(), Connection refused
$ _

Transfer HTTP connection to HTTPS in Pure C

I am having a serious problem transferring my HTTP connection socket program over to HTTPS connection socket code, how do I make only an HTTPS connection in pure C?
I am working on a package manager and am rewriting the connection.c file, the only thing this file contains is the code used to make the initial connection to the server containg packages, it does nothing else. I had this working 100% with an HTTP connection, however I need to move to an HTTPS connection and need to use LibreSSL; at the moment I am trying to use OpenSSL as I can't find anything on LibreSSL. The HTTP code I had is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include "repos.h"
#include "resolv.h"
short connection()
{
short socket_desc;
socket_desc = socket(AF_INET, SOCK_STREAM, 0); /* create socket with IPv4 and TCP protocol */
char host[17];
if (socket_desc == -1)
printf("could not create socket\n");
struct sockaddr_in *serv_addr = calloc(1, sizeof(struct sockaddr_in));
serv_addr->sin_family = AF_INET;
serv_addr->sin_port = htons(80);
resolv(DEFAULT_HOST, host); /* set repository to use */
if (inet_pton(AF_INET, host, &serv_addr->sin_addr) <= 0) {
printf("error");
free(serv_addr);
return -1;
}
if (connect(socket_desc, (struct sockaddr *)serv_addr, sizeof(*serv_addr)) < 0) {
printf("connection failed\n");
return 1;
}
else {
printf("connection initialized\n");
return 0;
}
/* close the connection */
free(serv_addr);
close(socket_desc);
return 0;
}
This works 100% and I want to just port this over to HTTPS. After looking at the horribly formatted OpenSSL client.c example (see here: https://wiki.openssl.org/index.php/SSL/TLS_Client) I got that code working on my system (had to make some changes to it), and then went off to port over my HTTP code to HTTPS. I worked on it for a bit and thought I got it working, I have been debugging it but can't figure out why it keeps failing. The code is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include "repos.h"
#include "resolv.h"
SSL *cSSL;
void initssl()
{
SSL_load_error_strings();
SSL_library_init();
OpenSSL_add_all_algorithms();
}
void destroyssl()
{
ERR_free_strings();
EVP_cleanup();
}
void shutdownssl()
{
SSL_shutdown(cSSL);
SSL_free(cSSL);
}
int main()
{
short socket_desc;
short socket_ssl;
char host[17];
socklen_t sock_size;
SSL_CTX *sslctx;
initssl();
socket_desc = socket(AF_INET, SOCK_STREAM, 0); /* create socket with IPv4 and TCP protocol */
if (socket_desc == -1)
printf("could not create socket\n");
struct sockaddr_in *serv_addr = calloc(1, sizeof(struct sockaddr_in));
serv_addr->sin_family = AF_INET;
serv_addr->sin_port = htons(443);
resolv(DEFAULT_HOST, host); /* resolve DEFAULT_HOST and store the ip in host */
if (inet_pton(AF_INET, host, &serv_addr->sin_addr) <= 0) {
printf("error");
free(serv_addr);
return -1;
}
bind(socket_desc, (struct sockaddr *)serv_addr, sizeof(struct sockaddr_in));
listen(socket_desc, 5);
sock_size = sizeof(struct sockaddr_in);
socket_ssl = accept(socket_desc, (struct sockaddr *)serv_addr, &sock_size); /* this is where hang occurs, however I am usnure why. I am reading docs and such and if I figure this out I will post the fix; however I would love some advice/help if anyone sees my error */
sslctx = SSL_CTX_new(SSLv23_server_method());
SSL_CTX_set_options(sslctx, SSL_OP_SINGLE_DH_USE);
short use_cert = SSL_CTX_use_certificate_file(sslctx, "/serverCertificate.pem" , SSL_FILETYPE_PEM);
short use_prv = SSL_CTX_use_PrivateKey_file(sslctx, "/serverCertificate.pem", SSL_FILETYPE_PEM);
cSSL = SSL_new(sslctx);
SSL_set_fd(cSSL, socket_ssl);
char ssl_err = SSL_accept(cSSL);
if(ssl_err <= 0) {
printf("connection failed\n");
shutdownssl();
}
else
printf("connected\n");
return 0;
}
Now I know it is missing some obvious things such as writing my own initssl (I am unsure why that isn't already in the lib, but I am starting to see why OpenBSD decided to fork). I left those out as I am more interested in this working with LibreSSL and don't believe you need them with LibreSSL. I tried using print statements to debug but they never get printed even when given at the top of main(). I am unsure why this isn't working and need some help getting this ported. The other files I wrote, repos.h and resolv.c can be seen below:
/* repos.h */
char DEFAULT_HOST[11] = "gitlab.com";
char DEFAULT_PAGE[24] = "Puffles_the_Dragon/core";
/* resolv.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <netdb.h>
short resolv(char *host, char *ip)
{
struct hostent *hp = calloc(1, sizeof(struct hostent));
hp = gethostbyname(host);
if (hp == NULL) {
fprintf(stderr, "gethostbyname() failed\n");
exit(1);
}
else {
short i = 0;
while (hp->h_addr_list[i] != NULL) {
inet_ntoa(*(struct in_addr *)(hp->h_addr_list[i]));
i++;
}
strlcpy(ip, inet_ntoa(*(struct in_addr *)(hp->h_addr_list[0])), 16);
}
return 0;
}
I know some of these calls are outdated due to IPv6, but I am going to add for IPv6 after I get this all working and port from BSD libc to musl libc.
I expected the HTTPS code to run and connect to the server thus printing connected, but it just runs and doesn't fail or print anything.

Can't Connect to Twitch IRC Server, problem with IP address, C language

I'm trying to build a ChatBot for Twitch entirely in C Language. But i'm having problems in connecting to the server: irc.chat.twitch.tv with port 6667. I'm calling gethostbyname() to retrieve the ip address of the hostname, but the connect function never establish the connection, and returns "Connection Failed".
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include "Authentication.h"
#include "MessageHandlers.h"
int main()
{
int sock;
struct sockaddr_in addr;
struct hostent * addr_info;
char * ip;
addr_info = gethostbyname("irc.chat.twitch.tv");
ip = inet_ntoa(*(struct in_addr *)addr_info->h_name);
printf("%s", ip);
addr.sin_family = AF_INET;
addr.sin_port = htons(6667);
addr.sin_addr.s_addr = inet_addr(ip);
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock < 0)
{
fprintf(stderr, "\nSocket Creation Failed\n");
exit(EXIT_FAILURE);
}
printf("\nConnecting to Twitch IRC Server...\n");
if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1)
{
fprintf(stderr, "\nConnection Failed\n");
exit(EXIT_FAILURE);
}
// SendAuthentication(sock);
/*
while(1)
{
OnMessageEvents(sock);
}
*/
exit(EXIT_SUCCESS);
}
Is there something i'm doing wrong? The twitch resolved ip address seems to be 105.114.99.45. I searched on Google for the actual ip address, but i didn't find any answers.
I used nslookup irc.chat.twitch.tv and tried all the ip addresses, but still i got "Connection Failed".
If i use telnet irc.chat.twitch.tv 6667 i get a connection and i can perform the login.
Resolved in comments above. The port number in struct sockaddr_in is in network endianness (aka big endian), while your computer is likely running as little endian. To assign it, you must use
addr.sin_port = htons(6667);
instead of
addr.sin_port = 6667;

C Socket Programming - Connecting to an External Source

I'm trying to get into socket programming with C and my problem is that no matter what I try I cannot get my client-server model to connect over the internet except through logging into my router and port forwarding the port I'm inputting in my program. Basically my server.c blocks and waits for a connection, then it sends the time of the server to the client once it connects. I've tried to open ports on both my machines like this:
sudo iptables -A INPUT -p tcp --dport 20001 -j ACCEPT
and I downloaded the iptables-persistent package that makes sure the rules stay on a reboot. iptables -L shows me that the ports are open on both machines, but the connection still times out. I know that somehow this is possible because Steam and Discord don't have to port forward anything and they still make it happen. I have a server at home so if the solution requires a 'middle man' server to facilitate a connection between two clients, then it won't be a problem for me. Also I am on two separate networks, so that's not the problem.
The server.c:
/* --- server.c --- */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
int main(int argc, char *argv[])
{
int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
char sendBuff[1025];
time_t ticks;
/* creates an UN-named socket inside the kernel and returns
* an integer known as socket descriptor
* This function takes domain/family as its first argument.
* For Internet family of IPv4 addresses we use AF_INET
*/
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr));
memset(sendBuff, '0', sizeof(sendBuff));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(20001);
/* The call to the function "bind()" assigns the details specified
* in the structure 『serv_addr' to the socket created in the step above
*/
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
/* The call to the function "listen()" with second argument as 10 specifies
* maximum number of client connections that server will queue for this listening
* socket.
*/
listen(listenfd, 10);
while(1)
{
/* In the call to accept(), the server is put to sleep and when for an incoming
* client request, the three way TCP handshake* is complete, the function accept()
* wakes up and returns the socket descriptor representing the client socket.
*/
connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
/* As soon as server gets a request from client, it prepares the date and time and
* writes on the client socket through the descriptor returned by accept()
*/
ticks = time(NULL);
snprintf(sendBuff, sizeof(sendBuff), "%.24s\r\n", ctime(&ticks));
write(connfd, sendBuff, strlen(sendBuff));
close(connfd);
sleep(1);
}
}
and client.c:
/* --- client.c --- */
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
int sockfd = 0, n = 0;
char recvBuff[1024];
struct sockaddr_in serv_addr;
if(argc != 2)
{
printf("\n Usage: %s <ip of server> \n",argv[0]);
return 1;
}
memset(recvBuff, '0',sizeof(recvBuff));
/* a socket is created through call to socket() function */
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Error : Could not create socket \n");
return 1;
}
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(20001);
if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr)<=0)
{
printf("\n inet_pton error occured\n");
return 1;
}
/* Information like IP address of the remote host and its port is
* bundled up in a structure and a call to function connect() is made
* which tries to connect this socket with the socket (IP address and port)
* of the remote host
*/
if( connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\n Error : Connect Failed \n");
return 1;
}
/* Once the sockets are connected, the server sends the data (date+time)
* on clients socket through clients socket descriptor and client can read it
* through normal read call on the its socket descriptor.
*/
while ( (n = read(sockfd, recvBuff, sizeof(recvBuff)-1)) > 0)
{
recvBuff[n] = 0;
if(fputs(recvBuff, stdout) == EOF)
{
printf("\n Error : Fputs error\n");
}
}
if(n < 0)
{
printf("\n Read error \n");
}
return 0;
}
This line is saying what port you're connecting to on the server
serv_addr.sin_port = htons(42020);
change it to the same port number as the server and it should work just fine.
serv_addr.sin_port = htons(20001);
#include <stdio.h>
#include "http.h"
#define MAX 4096
int main()
{
char s_msg[MAX], c_msg[MAX];
printf("%d", strlen(s_msg));
// Clean buffers:
memset(s_msg,'\0',sizeof(s_msg));
memset(c_msg,'\0',sizeof(c_msg));
char *msg = "GET / HTTP/1.1\r\nUser-Agent: Hellothere\r\nHost: HOSTNAME\r\n\r\n";
int soc = init_client();
int con = connection("HOSTNAME",80);
if(send(socket_desc, msg, strlen(msg), 0) < 0){
printf("Unable to send message\n");
return -1;
}
if (recv(socket_desc, c_msg , MAX, 0)<0)
{
printf("Failed to read from server\n");
return -1;
}
printf("Recieved from server : %s\n",c_msg);
return 0;
}
Using ngrok you need to use Host header

How to get site ip address using c

I am trying to build a HTTP request using sockets in c.
So, in order to navigate the socket to the correct site ip.
I need to get the site ip.
I have managed to get the host ip but that not always work.
The following code gets the host ip:
host = gethostbyname(host_name);
if (host != NULL) {
memcpy(&inp, host->h_addr_list[0], host->h_length);
sprintf(ip, "%s", inet_ntoa(inp));
}
But that not always work, for example if I want to send the socket to stackoverflow.com and get his HTML content.I used this code and the output was: "198.252.206.16".
And if you enter that ip you can see that it is a wrong ip,so what can I do?
Please help.
P.S that this all my code:
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <errno.h>
#include <assert.h>
int main(int argc, char **argv) {
if (argc < 2) {
fprintf(stderr, "usage: %s domain_name\nE.g. %s www.yahoo.com/lalal.html\n", argv[0], argv[0]);
return(0);
}
struct protoent *pr;
struct in_addr inp;
int x = 1;
int ret;
char buf[4192];
char ip[16];
struct hostent *host;
int sock, bytes_recieved;
struct sockaddr_in server_addr;
char url[strlen(argv[1])];
strcpy(url,argv[1]);
char *index_page = strstr(argv[1], "/");
char *host_name = strtok(url,"/");
char message[4000];
sprintf(message,"GET %s HTTP/1.1\r\nHost: %s\r\n\r\n",index_page,host_name);
printf("%s",message);
host = gethostbyname(host_name);
if (host != NULL) {
memcpy(&inp, host->h_addr_list[0], host->h_length);
sprintf(ip, "%s", inet_ntoa(inp));
}
else {
printf("ERROR - Host ip was not found.\n\n");
exit(1);
}
printf("%s\n",ip);
pr = getprotobyname("tcp");
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Socket");
exit(1);
}
printf("%s\n",message);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(80);
server_addr.sin_addr = *((struct in_addr *)host->h_addr);
bzero(&(server_addr.sin_zero),8);
if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {
perror("Connect");
exit(1);
}
write(sock, message, strlen(message));
while ((ret = read(sock, buf, 4192)) != 0) {
buf[ret]='\0';
fwrite(buf, ret, sizeof(char), stdout);
x++;
}
if (close(sock) == -1)
printf("Close socket error\n");
return 0;
}
StackExchange hosts multiple sites on the same server. 198.252.206.16 is the IP address of that server, and that is the correct IP address you need to connect your socket to.
When requesting an HTTP resource from a site that resides on a shared server, you must provide an HTTP Host header to specify the site's hostname so the server knows which site you are trying to access.
For example, if you go to http://198.252.206.16, the request would look like this:
(connect to 198.252.206.16)
GET / HTTP 1.1
Host: 198.252.206.16
...
If you go to http://www.stackoverflow.com, the request looks like this:
(connect to 198.252.206.16)
GET / HTTP 1.1
Host: www.stackoverflow.com
...
If you go to http://www.stackexchange.com, the request looks like this:
(connect to 198.252.206.16)
GET / HTTP 1.1
Host: www.stackexchange.com
...
Notice that they all connect to the same IP address.
There is no site associated with the 198.252.206.16 host, which is why you get the error message.
The Host header is required for all HTTP 1.1 requests, and is optional for HTTP 1.0 requests (but an HTTP 1.0 request will fail in this situation if the Host header is missing). It was designed specifically to support multiple sites on a shared server.

Resources