Persistent Connection in C socket programming - c

I have written a client code to create a socket and send a request to the client and as HTTP 1.1 uses Connection:Alive by default still the connection closes.How can i create a persistent connection such that the server listens to every request until the connection is closed.The client side code is:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
void error(char *msg){
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n,i;
int Max_Requests;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
Max_Requests=atoi(argv[3]);
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,(char *)&serv_addr.sin_addr.s_addr,server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
i=0;
while(i<Max_Requests){
printf("Please enter the message: ");
bzero(buffer,256);
fgets(buffer,255,stdin);
n = write(sockfd,buffer,strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
bzero(buffer,256);
n = read(sockfd,buffer,255);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
i++;
}
return 0;
}

The problem is your use of fgets to read input from the user to form the request.
The problem with it is how you use it, namely to read a single line that you send to the server as the request. You then promptly go to the read call and wait for the response, without having sent the full request and its headers.
That will lead the server to time-out and close the connection, since it haven't received a full request.

Related

How can I change my server so that multiple clients have access the shared data in the server?

Basically, I am doing a tcp project in c and I made it so multiple clients can connect to my server by using fork. In my server I have a linked list structure that keeps data that clients are sending. However, when I am sending data from the client to the linked list located in the server, the server creates a new linked list for that client . Instead of adding all client data to the same linked list. I know for certain its not a problem with the linked list. Fork() duplicates the process, so after calling fork there are actually 2 instances of my program running. So yeah I realized the clients aren't communicating with the same server? How should I fix this problem? Do I get rid of fork? Please conceptually explain to me what I must do. I'm not posting my actual code because it is sensitive . But here is basically what I am doing:
server:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
void dostuff(int); /* function prototype */
void error(char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, clilen, pid;
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);
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);
dostuff(newsockfd);
exit(0);
}
else close(newsockfd);
} /* end of while */
return 0; /* we never get here */
}
void dostuff (int sock)
{
int n;
char buffer[256];
bzero(buffer,256);
n = read(sock,buffer,255);
if (n < 0) error("ERROR reading from socket");
printf("Here is the message: %s\n",buffer);
n = write(sock,"I got your message",18);
if (n < 0) error("ERROR writing to socket");
client :
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
void error(char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
printf("Please enter the message: ");
bzero(buffer,256);
fgets(buffer,255,stdin);
n = write(sockfd,buffer,strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
bzero(buffer,256);
n = read(sockfd,buffer,255);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
return 0;
}
Because fork() creates a new process, you will need to use shared memory (shm_open(), shm_unlink(), mmap(),...). You can find based on this other question's answer.
You can get rid of fork and instead
a thread for each connection, which means you can share state between clients in your program. This will however require you to add synchronization (mutexes, etc.) around all shared data.
use a single thread in asynchronous/nonblocking mode (select/epoll/etc.) to serve all clients.

Unexpected output in IPC using sockets

I am trying to write a server that can handle at most 5 concurrent clients.
Whenever a client gets successfully connected to the server & the number of clients is less than or equal to 5, the server sends a welcome message, generates a 5 digit unique random number for identifying that client, sends this number to the client and prints this number in the console.If the number of clients tends to be greater than 5, then for each new request, it just sends a message "Connection Limit Exceeded" to the client & closes the connection.
Client just prints the messages sent by the server.
The problem I'm facing is that, the random number is not being propagated properly to the client.Few times the client prints the same number as generated by the server but few times the client just prints 0(as the variable storing incoming value of that random number is initialized to 0).
What could be the reason behind this?
Here are the codes for client and server:
server:
/* A simple server in the internet domain using TCP
The port number is passed as an argument
This version runs forever, forking off a separate
process for each connection
*/
#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 <time.h>
#include <stdlib.h>
void dostuff(int); /* function prototype */
void write_once (int sock);
void error(const char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, pid, count = 0;
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);
while (1) {
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
pid = fork();
count++;
if (pid < 0)
error("ERROR on fork");
if (pid == 0 && count <=5 ) {
close(sockfd);
dostuff(newsockfd);
exit(0);
}
if (pid == 0 && count >= 5 ) {
close(sockfd);
write_once(newsockfd);
exit(0);
}
else close(newsockfd);
} /* end of while */
close(sockfd);
return 0; /* we never get here */
}
/******** DOSTUFF() *********************
There is a separate instance of this function
for each connection. It handles all communication
once a connnection has been established.
*****************************************/
void dostuff (int sock)
{
int n;
char buffer[256];
bzero(buffer,256);
n = write(sock,"Welcome\n",8);
if (n < 0) error("ERROR writing to socket");
srand((unsigned int)time(NULL));
int r = rand() % 90000 + 10000;
int converted_r = htonl(r);
n = write(sock, &converted_r, sizeof(converted_r));
if (n < 0) error("ERROR writing to socket");
printf("%d\n", r);
}
void write_once (int sock)
{
int n;
char buffer[256];
bzero(buffer,256);
n = write(sock,"Connection Limit Exceeded!!",28);
if (n < 0) error("ERROR writing to socket");
}
client:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
void error(const char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
int received_int = 0;
char buffer[256];
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
bzero(buffer,256);
n = read(sockfd,buffer,255);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
n = read(sockfd, &received_int, sizeof(received_int));
if (n < 0)
error("ERROR reading from socket");
printf("%d\n", ntohl(received_int));
close(sockfd);
return 0;
}
Reference
The issue is that TCP is a stream oriented protocol, and not packet oriented. So it may happen that
The first read() of the client reads what the first write() of the server sent ("Welcome")
The second read() of the client reads what the second write() of the server sent (Your number)
This is what you expect and what sometimes happens.
However, it might also be that the client reads the data of both writes of the server at once! This usually happens when
either the server aggregated the two writes to a single tcp-packet
or the client reads the data after both tcp segments with data arrived
You cannot make sure what happens and cannot rely on any specific behaviour.
How to fix this depends solely on your protocol. If the first message is always "Welcome\n", then try to read only 8 bytes first. If you happen to read n < 8 bytes, you have to retry and read 8-n bytes to get the rest of the message. Subsequently read sizeof(received_int) bytes, also watching for the real number of bytes received.
If the message is of variable length you will have to use some kind of framing like a preceding length-byte or something like that.

unable to get my proxy server to send http requested information to client- Socket programming

My objective of my programs is to implement a proxy server that can be connected by a single client and would only allow http request.
The Requirements
To create a C based client-server architecture using sockets
The proxy server should be able to accept and service single client's http requests
Code
client.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
int sockfd, portnum, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if(argc < 3){
fprintf(stderr, "usage %s hostname port\n", argv[0]);
exit(1);
}
portnum = atoi(argv[2]);
sockfd= socket(AF_INET, SOCK_STREAM, 0);
if(sockfd <0){
perror("ERROR opening Socket");
exit(1);
}
server= gethostbyname(argv[1]);
if(sockfd == NULL){
fprintf(stderr,"ERROR, no such host\n");
exit(1);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portnum);
if(connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) <0){
fprintf(stderr,"ERROR, on connecting");
exit(1);
}
printf("Please enter the Host name: ");
bzero(buffer,256);
fgets(buffer,255,stdin);
n=write(sockfd,buffer,strlen(buffer));
if(n<0){
printf("Error writing to socket");
exit(1);
}
bzero(buffer,256);
n=read(sockfd,buffer,255);
if(n<0){
printf("ERROR reading from socket");
exit(1);
}
printf("%s\n", buffer);
return 0;
}
Proxy server.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <netdb.h>
#include <string.h>
int main(int argc, char *argv[]){
int sockfd, newsockfd, portnum, clilen;
char buffer[256], hostname[256];
pid_t p_id;
struct sockaddr_in serv_addr, cli_addr;
int n, pid;
if(argc < 2){
fprintf(stderr, "ERROR, NO PORT PROVIDED!\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);//socket is made
if(sockfd < 0){
fprintf(stderr,"ERROR opening socket!!");
exit(1);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
portnum = atoi(argv[1]);//port num
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(portnum);
if(bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0){
fprintf(stderr,"ERROR on binding");
exit(1);
}
if( listen(sockfd, 5) < 0){
printf("ERROR ON LISTEN");
exit(1);
}
// accept
clilen = sizeof(cli_addr);
do{
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if(newsockfd<0){
fprintf(stderr,"ERROR on accept\n");
exit(1);
}
pid=fork();
if(pid==0){
bzero(buffer, 256);
n= read(newsockfd, buffer, 255);
if(n<0){//message from client
fprintf(stderr,"ERROR Reading from socket\n");
exit(1);
}
strcpy(hostname, buffer);
printf("Here is the hostname : %s\n", hostname);
//variables used for acsessing webserver?
int sockwb, wbport, x;
struct sockaddr_in webser_addr;
struct hostent *wbhost;
char webbuf[510];//sending to webserver
wbport =80;//port used to access web server
sockwb = socket(AF_INET, SOCK_STREAM, 0);
if(sockwb <0){
printf("error opeing websocket\n");
exit(1);
}
wbhost= gethostbyname(hostname);
printf("%s", wbhost->h_name);
if(sockwb == -1){
printf("NO SUCH web HOST\n");
exit(1);
}
bzero((char*) &webser_addr, sizeof(webser_addr));
webser_addr.sin_family = AF_INET;
bcopy((char *)wbhost->h_addr,
(char *)&webser_addr.sin_addr.s_addr,
wbhost->h_length);
webser_addr.sin_port = htons(wbport);
if(connect(sockwb,(struct sockaddr *)&webser_addr,sizeof(webser_addr)) < 0){
printf("error on web connecting\n");
exit(1);
}
bzero(webbuf,510);
strcpy(webbuf, "GET http://");
strcat(webbuf, hostname);
strcat(webbuf, " HTTP/1.1");
printf("%s\n", webbuf);
x=write(sockwb,webbuf,strlen(webbuf));
if(x<0){
printf("error writing to web sock");
exit(1);
}
bzero(webbuf,510);
x=read(sockwb,webbuf,510);
if(n<0){
printf("error reading from web socket");
exit(1);
}
n = write(newsockfd, webbuf,255 );//write back to client
if (n<0){
fprintf(stderr,"ERROR WRITING to socket");
exit(1);
}
printf("%s\n", webbuf);
}//end of if pid==0
printf("closing client");
close(newsockfd);//closing client socket
}while(1);
return 0;
}
I have been able to implement a simple client-server exchange with sockets, my issue is with the Http request. I do have to access the web server through port 80 using the GET Method.
The way i have the input that the client is sending to the proxy server should be : www.NAME.com
The server doesn't seem to doing anything after the initial connection to the client.
As usual, null-terminated strings are not managed properly here. When following construct is used
send(sock, buff, strlen(buf));
The trailing null-terminated character is not sent. On the receiving side, there are two problems. First, recv(sock, buff, sizeof(buff)); can receive unpredictable amount of bytes - from 1 to the size of the string provided. So you need to read until you read all the message. Here comes the dilemma - how do you know how long is the actual message? The answer is that you either agree on the size of all the strings in advance, and than you always send that many bytes (regardless of actual string length) or you prefix the the string with it's size in the message. The second problem is that even if by luck the whole string is read, it is not null-terminated, and as such, unusable in the program. It has be null-terminated manually.

Am I creating the Protocol correctly?

I am trying to make a protocol (built ontop of TCP) that can send strings from the client to the server on port 457. Here is what I have so far:
Server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
void error(const char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
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);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
error("ERROR on accept");
bzero(buffer,256);
n = read(newsockfd,buffer,255);
if (n < 0) error("ERROR reading from socket");
printf("Here is the message: %s\n",buffer);
n = write(newsockfd,"U got your messaze",18);
if (n < 0) error("ERROR writing to socket");
close(newsockfd);
close(sockfd);
return 0;
}
Client.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
void error(const char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
printf("Please enter the message: ");
bzero(buffer,256);
fgets(buffer,255,stdin);
n = write(sockfd,buffer,strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
bzero(buffer,256);
n = read(sockfd,buffer,255);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
close(sockfd);
return 0;
}
I feel as though I am not setting up the protocol properly. Am I?
You should write a specification for your protocol first. Then, after reviewing it, you implement the specification. You are basically asking us to reverse engineer your protocol. This is a backwards approach to creating a protocol. You should already have a clear intent of what your program needs to do before you begin implementing it.
Your server program acts as a limited kind of ECHO server, in that no more than 255 bytes of input from the client is accepted. Whatever the server was able to read is logged to the console, and the message U got your messaze is sent to the client as a response.
Some issues you may want to address:
Although unlikely, it is possible that your read() call returns with less data than what the client sent, even if the client sends less than 256 bytes. For example, if the client sends aaaaaaaaaa one byte at a time, your server might only see the first a, and assume it is a complete message.
You don't take precautions against writing to an already closed connection. This may generate SIGPIPE, and cause your program to exit unexpectedly.
Signals generally may interrupt your system calls. You should detect this condition and restart your system calls if that occurs.
You have some incorrect types:
htons expects uint16_t as parameter
htons((uint16_t)portno);
read() and write() expects ssize_t
ssize_t n;
bzero is deprecated, use
memset(buffer, 0, sizeof(buffer));
bcopy is deprecated, use
memmove(server->h_addr, &serv_addr.sin_addr.s_addr, server->h_length);
NUL terminate buffer when read() is used
/* bzero(buffer,256); Not needed */
n = read(newsockfd,buffer,255);
if (n < 0) error("ERROR reading from socket");
buffer[n]= '\0'; /* here */
printf("Here is the message: %s\n",buffer);
And note that modern programs uses send() and recv() instead of read() and write()
Finally, don't use magic numbers
fgets(buffer, 255, stdin);
instead:
fgets(buffer, sizeof(buffer), stdin); /* 256 */
And why 255? the fgets() function shall read bytes from stream into the array pointed to by s, until n-1 bytes are read, so 256 is correct.

C sockets: forward a request to port 80 and read response

I have the following code (I'm working from code at http://www.linuxhowtos.org/C_C++/socket.htm) which I'm trying to turn into a proxy server:
#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 <netdb.h>
void dostuff(int); /* function prototype */
void error(const char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
//setup proxy:
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);
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);
dostuff(newsockfd);
exit(0);
}
else close(newsockfd);
} /* end of while */
close(sockfd);
return 0; /* we never get here */
}
/******** DOSTUFF() *********************
There is a separate instance of this function
for each connection. It handles all communication
once a connnection has been established.
*****************************************/
void dostuff (int sock)
{
int n;
char buffer[256];
bzero(buffer,256);
n = read(sock,buffer,255);
if (n < 0){
error("***ERROR reading from socket");
}
//printf("Here is the message: %s\n",buffer);
/*
***Forward message to port 80 and read response here
*/
n = write(sock,"I got your message",18);
if (n < 0) error("***ERROR writing to socket");
}
In the function "dostuff" I want to write 'buffer' to port 80, read the response and write this response back over port 20000 (argv[1]).
At the moment, when I set my browser's proxy to 172.16.1.218:20000, all I get is "I got your message". I want to change this to the response from the webpage!
Any pointers in the right direction greatly appreciated.
Here's what I've tried sofar (replace multi-line comment "Forward message to port 80 and read response here" with this code):
int sockfdi, portnoi, ni;
struct sockaddr_in serv_addri;
struct hostent *serveri;
portnoi =80;
sockfdi = socket(AF_INET, SOCK_STREAM, 0);
if (sockfdi < 0){
error("***ERROR opening socket");
}
serveri = gethostbyname("172.16.1.218");
if (serveri == NULL){
fprintf(stderr,"***ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addri, sizeof(serv_addri));
serv_addri.sin_family = AF_INET;
bcopy((char *)serveri->h_addr, (char *)&serv_addri.sin_addr.s_addr, serveri->h_length);
serv_addri.sin_port = htons(portnoi);
if (connect(sockfdi,(struct sockaddr *) &serv_addri,sizeof(serv_addri)) < 0){
error("***ERROR connecting");
}
printf("Please enter the message: ");
bzero(buffer,256);
But every time I try to connect via my webbrowser, the server echos: "***ERROR connecting: Connection refused"
Many thanks in advance,
This is a non-trivial task you set out to do. Currently, you're missing three things, an easy one and two difficult ones:
You have to open a network connection to the server you want to forward the call to (rather easy, see socket() and connect()).
You'll then have a duplex connection, that is two concurrent streams of data, one going from the client to the forwarded server and one from the forwarded server to the client. In order to cope with this concurrency, you either need two threads with blocking I/O or some sort of non-blocking I/O (see select() or AIO).
If you forward an HTTP request without changes to another server, you'll likely end up with invalid server names and IP addresses in the request. The request will then be rejected. So you'll need to parse the HTTP header, do some replacements and forward the modified HTTP request.

Resources