Segmentation fault in proxy server program - c

I am trying to create a simple proxy server in c. I have used this url parser to parse the http request from the client. It returns a pointer to this structure:
struct parsed_url {
char *scheme; /* mandatory */
char *host; /* mandatory */
char *port; /* optional */
char *path; /* optional */
char *query; /* optional */
char *fragment; /* optional */
char *username; /* optional */
char *password; /* optional */
};
When I print the host name after parsing a http request from a client, it displays correct result like "www.google.com". But when I pass this hostname to gethostbyname(), it gives me segmentation fault. I am not bale to figure out why this happens.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include "url_parser.h"
int main(int argc,char *argv[])
{
struct sockaddr_in server,client;
struct hostent *host;
int s1,s2,s3,len;
int port;
char ip[100];
char path[100];
int p;
struct parsed_url *url = NULL;
int n;
char buffer[500];
char site[500];
port = atoi(argv[1]);
bzero((char *)&server,sizeof(server));
server.sin_port = htons(port);
server.sin_addr.s_addr = INADDR_ANY;
server.sin_family = AF_INET;
s1 = socket(AF_INET,SOCK_STREAM,0);
if(bind(s1,(struct sockaddr *)&server,sizeof(server)) == -1) {
perror("can't bind");
exit(1);
}
if(listen(s1,10) == -1) {
perror("coudnt't listen");
exit(1);
}
len = sizeof(client);
s2 = accept(s1,(struct sockaddr *)&client,&len);
if(s2 == -1) {
perror("coudnt aceept");
exit(1);
}
memset(buffer,0,sizeof(buffer));
n = recv(s2,buffer,500,0);
if(n < 0) {
perror("not recieved");
exit(1);
}
buffer[n] = '\0';
url = parse_url(buffer);
bzero((char *)&client,sizeof(client));
client.sin_port = htons(80);
printf("%s %d",url->host,strlen(url->host));
host = gethostbyname((char *)url->host);
if(!host) {
herror("host error");
}
bcopy((char *)host->h_addr,(char *)&client.sin_addr.s_addr,host->h_length);
client.sin_family = AF_INET;
s3 = socket(AF_INET,SOCK_STREAM,0);
if(connect(s3,(struct sockaddr *)&client,sizeof(client)) == -1) {
perror("can't connect\n");
exit(1);
}
sprintf(site,"GET http://%s/ HTTP/1.0\n\n",url->host);
n = send(s3,site,strlen(site),0);
if(n < 0) {
perror("message not sent");
exit(1);
}
while(1) {
memset(site,0,sizeof(site));
n = recv(s3,site,500,0);
if(n < 0) {
perror("coudnot read");
exit(1);
}
//site[n] = '\0';
send(s2,site,strlen(site),0);
}
close(s1);
close(s2);
return 0;
}
The url_parser uses this to parse.

Related

Writing content from struct into a file using fwrite

I am trying to write data from struct into a a file. For instance the data is found in newpackets.data. I am trying to write that into a file, but keep getting segfault. I have looked at other questions on here, but could not find a solution. Adding my code below. How can i solve this issue ? Thank you
to run server do ./server 8500 1
to run client do ./client 127.0.0.1 8500 500 3 ex.txt exout.txt
ex.txt will need to be made and then write random words into it. for instance can be like 85 characters
//server side
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/socket.h>
#include <stdint.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
#include <errno.h>
#include "sys/un.h"
#define MAXLINE 32768
struct ackdata
{
int ack;
};
struct packetdata
{
int seqnumber;
int lenght;
char data[MAXLINE];
int type;
};
void dg_echo (int sockfd, struct sockaddr *pcliaddr, socklen_t clilen);
int
main (int argc, char *argv[])
{
int sockfd;
struct sockaddr_in servaddr, cliaddr;
int SERV_PORT = atoi (argv[1]); ///This will grab the port to listen to
int dropc = atoi (argv[2]);
if (SERV_PORT <= 1023)
{
fprintf (stderr, "Error: Port given can not be less than 1023\n");
exit (1);
}
if (SERV_PORT > 65535)
{
fprintf (stderr,
"Error: Port given can not be more than 65535 or less than 1024\n");
exit (1);
}
sockfd = socket (AF_INET, SOCK_DGRAM, 0);
bzero (&servaddr, sizeof (servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htons (INADDR_ANY);
servaddr.sin_port = htons (SERV_PORT);
int bb = bind (sockfd, (struct sockaddr *) &servaddr, sizeof (servaddr));
if (bb < 0)
{
fprintf (stderr, "Binding failure");
}
dg_echo (sockfd, (struct sockaddr *) &cliaddr, sizeof (cliaddr));
close (sockfd);
return 0;
}
void
dg_echo (int sockfd, struct sockaddr *pcliaddr, socklen_t clilen)
{
int n;
FILE *outfile = NULL;
socklen_t len;
char mesg[MAXLINE];
struct packetdata newpackets;
char filename[MAXLINE];
recvfrom (sockfd, filename, MAXLINE, 0, pcliaddr, &len);
printf ("Name: %s", filename);
for (;;)
{
len = clilen;
//printf("HERe");
if ((outfile = fopen (filename, "a")) == NULL)
{
fprintf (stderr, "\nwriting File was not opened\n");
exit (1);
}
ssize_t rlen =recvfrom(sockfd, &newpackets, sizeof (newpackets), 0, pcliaddr, &len);
if (rlen ==-1){
printf ("failed recv");
return 1;
}
printf ("\nData: %s\n", newpackets.data);
//fprintf(outfile, "%d",newpackets.data );
fwrite(newpackets.data,rlen,1,outfile);
// sendto(sockfd, mesg, n, 0, pcliaddr, len);
}
}
Here is the client code:
//client side
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/socket.h>
#include <stdint.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
#include <errno.h>
#include <math.h>
#include <sys/time.h>
#include <string.h>
#include <time.h>
#define MAXLINE 4096
#define totaltries 3
struct packetdata data (int seqnumber, int lenght, char*data);
struct packetdata
{
int seqnumber;
int lenght;
char data[MAXLINE];
int type;
};
struct ackdata
{
int ack;
int type;
};
int main (int argc, char *argv[])
{
int sockfd;
struct sockaddr_in servaddr;
FILE *infile = NULL;
int countpackets;
float calc;
int tries = 0;
int base = 0;
int sequencenumber = 0;
int datasize =0;
int winsz = atoi (argv[4]); //this is for the window size
int mtu = atoi (argv[3]); //for mtu
int SERV_PORT = atoi (argv[2]); // the port to listen to
char sendline[MAXLINE], recvline[MAXLINE];
struct packetdata forpackets;
if (mtu <= 0)
{
fprintf (stderr, "MTU Error: mtu can not be less than or equal to 0\n");
exit (1);
}
//you shouldnt use any ports from 0-1023
//1024-65535 are fines
if (SERV_PORT <= 1023)
{
fprintf (stderr, "Port Error: Port given can not be less than 1023\n");
exit (1);
}
if (SERV_PORT > 65535)
{
fprintf (stderr,
"Port Error: Port given can not be more than 65535 or less than 1024\n");
exit (1);
}
bzero (&servaddr, sizeof (servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons (SERV_PORT);
if (inet_pton (AF_INET, argv[1], &servaddr.sin_addr) <= 0)
{
fprintf (stderr, "Inet Pton error");
return 1;
}
if ((sockfd = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
{
fprintf (stderr, "\nsocket error\n");
return 1;
}
if ((infile = fopen (argv[5], "r")) == NULL)
{
fprintf (stderr, "\nReading File was not opened\n");
return 1;
}
//file name sending
char filename[MAXLINE];
strcpy(filename, argv[6]);
//printf("Filename: %c", filename);
sendto(sockfd, filename, MAXLINE, 0, (struct sockaddr * ) & servaddr, sizeof(servaddr));
//this is for calculations
fseek (infile, 0, SEEK_END);
countpackets = ftell (infile);
fseek (infile, 0, SEEK_SET);
// printf("countpackets %d\n",countpackets);
// printf("\nMTU %d\n",mtu);
calc = countpackets / mtu; //how many buffer is
if (countpackets % mtu)
{
calc++;
}
printf("\nCalc %f\n",calc);
char fordata[mtu];
//while(1){
while (calc>=sequencenumber && sequencenumber-base<=winsz){
fread(forpackets.data, sizeof(recvline), 1, infile);
//printf("%s", forpackets.data);
// strcpy(fordata, forpackets.data);
strncpy(fordata,(sequencenumber*mtu+forpackets.data),mtu);
printf("%s", fordata);
forpackets = data(sequencenumber,datasize, fordata );
printf("\nSending Packet: %d\n", sequencenumber);
if (sendto(sockfd, &forpackets, sizeof(forpackets), 0, (struct sockaddr * ) & servaddr, sizeof(servaddr)) == -1) {
printf("failed sending");
return 1;
}else{
sequencenumber++;
}
}
// }
close(sockfd);
fclose(infile);
}
struct packetdata data (int seqnumber, int lenght, char*data){
struct packetdata dataa;
dataa. seqnumber = seqnumber;
dataa. lenght = lenght;
dataa. type = 1;
memset(dataa.data, 0, MAXLINE);
strcpy(dataa.data, data);
return dataa;
}
Okay, just to recap the comments:
outfile was missing an fopen call, so the server fwrite would segfault
After the fix, the output file would get extraneous zeros because the length given to fwrite was the whole size rather than the returned value of recvfrom
Actually, the correct length is the length value inside the packet
You're on the right track. The struct you devised has the right things in it (e.g. sequence number, type, length, data field).
I've refactored the server and client code.
An additional issue is that the server didn't know when to stop writing the output file. There are several ways to do this. But, the one I chose was for the client to send an extra data packet with a length field of 0.
I've adjusted both client and server to do this.
Here is the refactored server code:
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/socket.h>
#include <stdint.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
#include <errno.h>
#include <sys/un.h>
#define MAXLINE 32768
struct ackdata {
int ack;
};
struct packetdata {
int seqnumber;
int length;
char data[MAXLINE];
int type;
};
void dg_echo(int sockfd, struct sockaddr *pcliaddr, socklen_t clilen);
int
main(int argc, char *argv[])
{
int sockfd;
struct sockaddr_in servaddr, cliaddr;
#if 1
if (argc < 2) {
printf("usage: serv_port\n");
exit(1);
}
#endif
int SERV_PORT = atoi(argv[1]); // /This will grab the port to listen to
#if 0
int dropc = atoi(argv[2]);
#endif
if (SERV_PORT <= 1023) {
fprintf(stderr, "Error: Port given can not be less than 1023\n");
exit(1);
}
if (SERV_PORT > 65535) {
fprintf(stderr, "Error: Port given can not be more than 65535 or less than 1024\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htons(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
int bb = bind(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
if (bb < 0) {
fprintf(stderr, "Binding failure");
}
dg_echo(sockfd, (struct sockaddr *) &cliaddr, sizeof(cliaddr));
close(sockfd);
return 0;
}
void
dg_echo(int sockfd, struct sockaddr *pcliaddr, socklen_t clilen)
{
int n;
FILE *outfile = NULL;
socklen_t len;
char mesg[MAXLINE];
struct packetdata newpackets;
char filename[MAXLINE];
recvfrom(sockfd, filename, MAXLINE, 0, pcliaddr, &len);
#if 0
printf("Name: %s", filename);
#else
printf("Name: %s\n", filename);
outfile = fopen(filename,"w");
#endif
for (;;) {
len = clilen;
// printf("HERe");
if (recvfrom(sockfd, &newpackets, sizeof(newpackets), 0, pcliaddr, &len) == -1) {
printf("failed recv");
break;
}
printf("DEBUG: seqnumber=%d type=%d length=%d\n",
newpackets.seqnumber,newpackets.type,newpackets.length);
// end of file
if (newpackets.length == 0)
break;
//printf("\nData: %s\n", newpackets.data);
fwrite(newpackets.data, newpackets.length, 1, outfile);
// sendto(sockfd, mesg, n, 0, pcliaddr, len);
}
if (outfile != NULL)
fclose(outfile);
}
And, here is the refactored client code. I cleaned it up a bit.
I changed the code to do the fread directly into the packet struct's data field.
I changed the data function to take a pointer arg to the packet rather than returning one. This eliminates some unnecessary copying
I added an extra zero length data packet to indicate EOF
I changed the primary data read/write loop to look at the returned length from fread rather than (pre)calculate the number of packets.
//client side
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/socket.h>
#include <stdint.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
#include <errno.h>
#include <math.h>
#include <sys/time.h>
#include <string.h>
#include <time.h>
#define MAXLINE 4096
#define totaltries 3
struct packetdata {
int seqnumber;
int length;
char data[MAXLINE];
int type;
};
struct ackdata {
int ack;
int type;
};
void
data(struct packetdata *pkt,int seqnumber, int length, char *data)
{
pkt->seqnumber = seqnumber;
pkt->length = length;
pkt->type = 1;
if ((length > 0) && (data != NULL))
memcpy(pkt->data, data, length);
}
int
main(int argc, char *argv[])
{
int sockfd;
struct sockaddr_in servaddr;
FILE *infile = NULL;
int countpackets;
float calc;
int tries = 0;
int base = 0;
int sequencenumber = 0;
int datasize = 0;
int winsz = atoi(argv[4]); // this is for the window size
int mtu = atoi(argv[3]); // for mtu
int SERV_PORT = atoi(argv[2]); // the port to listen to
char sendline[MAXLINE],
recvline[MAXLINE];
struct packetdata forpackets;
if (mtu <= 0) {
fprintf(stderr, "MTU Error: mtu can not be less than or equal to 0\n");
exit(1);
}
// you shouldnt use any ports from 0-1023
// 1024-65535 are fines
if (SERV_PORT <= 1023) {
fprintf(stderr, "Port Error: Port given can not be less than 1023\n");
exit(1);
}
if (SERV_PORT > 65535) {
fprintf(stderr, "Port Error: Port given can not be more than 65535 or less than 1024\n");
exit(1);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) {
fprintf(stderr, "Inet Pton error");
return 1;
}
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
fprintf(stderr, "\nsocket error\n");
return 1;
}
if ((infile = fopen(argv[5], "r")) == NULL) {
fprintf(stderr, "\nReading File was not opened\n");
return 1;
}
// file name sending
char filename[MAXLINE];
strcpy(filename, argv[6]);
// printf("Filename: %c", filename);
sendto(sockfd, filename, MAXLINE, 0, (struct sockaddr *) &servaddr,
sizeof(servaddr));
// this is for calculations
fseek(infile, 0, SEEK_END);
countpackets = ftell(infile);
fseek(infile, 0, SEEK_SET);
// printf("countpackets %d\n",countpackets);
// printf("\nMTU %d\n",mtu);
calc = countpackets / mtu; // how many buffer is
if (countpackets % mtu) {
calc++;
}
printf("\nCalc %f\n", calc);
// while(1){
#if 0
while (calc >= sequencenumber && sequencenumber - base <= winsz) {
#else
while (1) {
#endif
ssize_t rlen = fread(forpackets.data, 1, sizeof(forpackets.data),
infile);
data(&forpackets,sequencenumber, rlen, NULL);
printf("\nSending Packet: %d rlen=%d\n", sequencenumber,rlen);
if (sendto(sockfd, &forpackets, sizeof(forpackets), 0,
(struct sockaddr *) &servaddr, sizeof(servaddr)) == -1) {
printf("failed sending");
return 1;
}
else {
sequencenumber++;
}
if (rlen == 0)
break;
}
// }
close(sockfd);
fclose(infile);
return 0;
}
Note that the client and server are "one-shots". That is, the server exits after receiving a given file.
Also, one change I didn't make was to send/receive the filename within a packet (with a different type field).
I'd change the programs to send only packet structs.
Then, the server could have an outer loop, to service new/different requests (e.g. it could receive a file, then send a file, etc.)
With various type fields (e.g.):
send file to server (data is filename)
send file to client (data is filename)
file data (sent by client and/or server and length of 0 indicates EOF)
close connection (sent by client to server)
This may be a bit of overkill for the scope of your project ...
The server could look at the IP address from recvfrom and keep some state in a "connection" struct, based on a match to the client IP address. For example, the connection struct could hold the outfile stream (instead of a single instance).
Then, the server could handle multiple/many client streams, interspersed on the same/single socket descriptor.
UPDATE:
Hey craig. TYSM. But is there a way, where the server is not one shot go? –
juststruggle
It starts by adding my suggestion about sending the filename inside a packet with a type.
And, having the server loop do a switch (pkt.type).
I've added the ruminants of that in the code below. The client is very similar in function to before. The server will now loop after file transfer, waiting for other packets.
Note that there is a bunch of similar code between server and client. I moved some of that to a common.c file. Note that this is crude. I'd like to have a common.h for definitions and function prototypes and a common.c for common functions. But, IRL, I am being "summoned" :-) so I don't have time to fix that.
I moved the struct definition to that file. In the process, I notice that the size of the data element is different between client and server. That's a bug because type is at the end and would be elided/truncated because of the differing lengths of data
Here's common.c:
// common.c -- common code
#define MAXLINE 1024
#define totaltries 3
#ifdef DEBUG
#define dbgprt(_fmt...) printf(_fmt)
#else
#define dbgprt(_fmt...) do { } while (0)
#endif
struct packetdata {
int type;
int seqnumber;
int length;
char data[MAXLINE];
};
struct ackdata {
int ack;
int type;
};
enum {
TYPE_TOSVR,
TYPE_TOCLI,
TYPE_DATA
};
void
pktprep(struct packetdata *pkt,int type,int seqnumber, int length, char *data)
{
pkt->type = type;
pkt->seqnumber = seqnumber;
pkt->length = length;
if ((length > 0) && (data != NULL))
memcpy(pkt->data, data, length);
dbgprt("pktprep: SENDPKT seq=%d type=%d length=%d\n",
seqnumber,type,length);
}
Here is server.c:
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/socket.h>
#include <stdint.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
#include <errno.h>
#include <sys/un.h>
#include "common.c"
void dg_echo(int sockfd, struct sockaddr *pcliaddr, socklen_t clilen);
int
main(int argc, char *argv[])
{
int sockfd;
struct sockaddr_in servaddr, cliaddr;
#if 1
if (argc < 2) {
printf("usage: serv_port\n");
exit(1);
}
#endif
int SERV_PORT = atoi(argv[1]); // /This will grab the port to listen to
#if 0
int dropc = atoi(argv[2]);
#endif
if (SERV_PORT <= 1023) {
fprintf(stderr, "Error: Port given can not be less than 1023\n");
exit(1);
}
if (SERV_PORT > 65535) {
fprintf(stderr, "Error: Port given can not be more than 65535 or less than 1024\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htons(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
int bb = bind(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
if (bb < 0) {
fprintf(stderr, "Binding failure");
}
dg_echo(sockfd, (struct sockaddr *) &cliaddr, sizeof(cliaddr));
close(sockfd);
return 0;
}
void
dg_echo(int sockfd, struct sockaddr *pcliaddr, socklen_t clilen)
{
int n;
FILE *outfile = NULL;
socklen_t len;
char mesg[MAXLINE];
struct packetdata pkt;
char filename[MAXLINE];
for (;;) {
len = clilen;
// printf("HERe");
if (recvfrom(sockfd, &pkt, sizeof(pkt), 0, pcliaddr, &len) == -1) {
printf("failed recv");
break;
}
dbgprt("DEBUG: seqnumber=%d type=%d length=%d\n",
pkt.seqnumber,pkt.type,pkt.length);
switch (pkt.type) {
case TYPE_TOSVR:
dbgprt("TOSVR: %s\n", pkt.data);
if (outfile == NULL)
outfile = fopen(pkt.data,"w");
break;
case TYPE_DATA:
// end of file
if (pkt.length == 0) {
if (outfile != NULL) {
fclose(outfile);
outfile = NULL;
}
break;
}
//dbgprt("\nData: %s\n", pkt.data);
if (outfile != NULL)
fwrite(pkt.data, pkt.length, 1, outfile);
break;
}
}
if (outfile != NULL)
fclose(outfile);
}
And, here is client.c:
//client side
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/socket.h>
#include <stdint.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
#include <errno.h>
#include <math.h>
#include <sys/time.h>
#include <string.h>
#include <time.h>
#include "common.c"
int
main(int argc, char *argv[])
{
int sockfd;
struct sockaddr_in servaddr;
FILE *infile = NULL;
int countpackets;
float calc;
int tries = 0;
int base = 0;
int sequencenumber = 0;
int datasize = 0;
int winsz = atoi(argv[4]); // this is for the window size
int mtu = atoi(argv[3]); // for mtu
int SERV_PORT = atoi(argv[2]); // the port to listen to
char sendline[MAXLINE],
recvline[MAXLINE];
struct packetdata pkt;
if (mtu <= 0) {
fprintf(stderr, "MTU Error: mtu can not be less than or equal to 0\n");
exit(1);
}
// you shouldnt use any ports from 0-1023
// 1024-65535 are fines
if (SERV_PORT <= 1023) {
fprintf(stderr, "Port Error: Port given can not be less than 1023\n");
exit(1);
}
if (SERV_PORT > 65535) {
fprintf(stderr, "Port Error: Port given can not be more than 65535 or less than 1024\n");
exit(1);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) {
fprintf(stderr, "Inet Pton error");
return 1;
}
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
fprintf(stderr, "\nsocket error\n");
return 1;
}
if ((infile = fopen(argv[5], "r")) == NULL) {
fprintf(stderr, "\nReading File was not opened\n");
return 1;
}
// file name sending
char filename[MAXLINE];
pktprep(&pkt,TYPE_TOSVR,sequencenumber++,strlen(argv[6]) + 1,argv[6]);
// printf("Filename: %c", filename);
#if 0
sendto(sockfd, filename, MAXLINE, 0, (struct sockaddr *) &servaddr,
sizeof(servaddr));
#else
sendto(sockfd, &pkt, sizeof(pkt), 0,
(struct sockaddr *) &servaddr, sizeof(servaddr));
#endif
// this is for calculations
fseek(infile, 0, SEEK_END);
countpackets = ftell(infile);
fseek(infile, 0, SEEK_SET);
// printf("countpackets %d\n",countpackets);
// printf("\nMTU %d\n",mtu);
calc = countpackets / mtu; // how many buffer is
if (countpackets % mtu) {
calc++;
}
dbgprt("\nCalc %f\n", calc);
// while(1){
#if 0
while (calc >= sequencenumber && sequencenumber - base <= winsz) {
#else
while (1) {
#endif
ssize_t rlen = fread(pkt.data, 1, sizeof(pkt.data),
infile);
pktprep(&pkt,TYPE_DATA,sequencenumber, rlen, NULL);
if (sendto(sockfd, &pkt, sizeof(pkt), 0,
(struct sockaddr *) &servaddr, sizeof(servaddr)) == -1) {
printf("failed sending");
return 1;
}
else {
sequencenumber++;
}
if (rlen == 0)
break;
}
// }
close(sockfd);
fclose(infile);
return 0;
}
Compile server.c and client.c with -DDEBUG to start.

Using printf with threads and socket programming

I was making a server using socket programming that echoes what the client says to him. But when I print out the message(send by client) and it's length, the message and it's length don't match. I am using printf to print.
What I basically want is to close the connection when the client types "exit". But strcmp("exit",clientmessage) is not working.
server code:
//for running type ./a.out anyportnumber
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
void *function(void *s)
{
int s1;
int n;
char rmsg[500];
s1 = *(int *)s;
while((n = read(s1,rmsg,499)) > 0) {
rmsg[n] = '\0';
printf("%s %d\n",rmsg,strlen(rmsg));
bzero(rmsg,499);
}
pthread_exit(NULL);
}
int main(int arrc,char *argv[])
{
struct sockaddr_in server,client;
int s1,len;
int s2;
int n;
int i = 0;
int port;
pthread_t t1;
char message[500];
port = atoi(argv[1]);
bzero((char *)&server,sizeof(server));
server.sin_port = htons(port);
server.sin_addr.s_addr = INADDR_ANY;
server.sin_family = AF_INET;
s1 = socket(AF_INET,SOCK_STREAM,0);
if(s1 == -1) {
perror("socket not created\n");
exit(1);
}
if(bind(s1,(struct sockaddr *)&server,sizeof(struct sockaddr)) == -1) {
perror("socket not binded\n");
exit(1);
}
if(listen(s1,5) == -1) {
perror("unable to listen");
exit(1);
}
len = sizeof(struct sockaddr_in);
s2 = accept(s1,(struct sockaddr *)&client,&len);
pthread_create(&t1,NULL,function,(void *)&s2);
pthread_join(t1,NULL);
close(s2);
close(s1);
return 0;
}
client side input:
shivam#shivam-HP-Pavilion-15-Notebook-PC:~$ telnet localhost 8009
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hhh
jhiklmnop
Server side output:
shivam#shivam-HP-Pavilion-15-Notebook-PC:~/Study/chat$ ./a.out 8009
hhh
5
jhiklmnop
11
Edited code:
//for running type ./a.out anyportnumber
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
void *function(void *s)
{
int s1;
int n;
char rmsg[500];
s1 = *(int *)s;
char d[] = {'e','x','i','t','\0'};
while((n = read(s1,rmsg,499)) > 0) {
rmsg[n-2] = '\0';
if(strcmp(d,rmsg) == 0) {
write(s1,"bye",3);
close(s1);
}
rmsg[n-2] = '\n';
rmsg[n-1] = '\0';
write(s1,rmsg,strlen(rmsg));
bzero(rmsg,499);
}
pthread_exit(NULL);
}
int main(int arrc,char *argv[])
{
struct sockaddr_in server,client;
int s1,len;
int s2;
int n;
int i = 0;
int port;
pthread_t t1;
char message[500];
port = atoi(argv[1]);
bzero((char *)&server,sizeof(server));
server.sin_port = htons(port);
server.sin_addr.s_addr = INADDR_ANY;
server.sin_family = AF_INET;
s1 = socket(AF_INET,SOCK_STREAM,0);
if(s1 == -1) {
perror("socket not created\n");
exit(1);
}
if(bind(s1,(struct sockaddr *)&server,sizeof(struct sockaddr)) == -1) {
perror("socket not binded\n");
exit(1);
}
if(listen(s1,5) == -1) {
perror("unable to listen");
exit(1);
}
len = sizeof(struct sockaddr_in);
s2 = accept(s1,(struct sockaddr *)&client,&len);
pthread_create(&t1,NULL,function,(void *)&s2);
pthread_join(t1,NULL);
close(s2);
close(s1);
return 0;
}
TCP is a stream-oriented protocol, there are no message boundaries. So you cannot write application logic that depends on the return value of read() as you are doing.
Workarounds for this are length-prefixed strings, or sending the NUL terminator through the socket. You can dream up other mechanisms too, but the client must, within the data stream, tell the server where the message ends; the TCP layer won't do that.
Besides the characters the user is typing in, you're also getting a carriage return (0xd) and linefeed (0xa) character when the user presses the Enter key. That's why you're getting a number 2 larger than you might expect.

C: How do you read and unpack a message over a socket?

I am trying to receive an updated message over the socket and unpack the
data. I want to use the update_client function to update the server's
internal representation of the client co-ordinates and respond to the
client with the required value.
I think I should use recv to read the full message (of length UPDATE_CMD_LEN) into buffer.
Then unpack data having message in the following format:
U<id><fields of gpscoords>
Character 'U' (meaning update), followed by ID of the client (unsigned char)
and then the gpscoord structure in network format.
This is a rough idea of how to do it but I don't know how:
[1] Unpack ID
[2] Unpack coordinates with int update_client(unsigned char id, gpscoords *pos
which takes ID and pointer to position struct, returns -1 on error and 0 on success
The server should then respond to client using sendto function and reply
NO_RES on error and SUCC_RES on success.
void do_update(int sockfd, struct sockaddr_in *clientaddr) {
char msg[UPDATE_CMD_LEN];
recv(sockfd, msg, UPDATE_CMD_LEN, flags);
fprintf(stderr, "do_update not implemented!\n");
exit(-1);
}
client.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include "gps.h"
#define CMD_LEN 10
#define LINE_LEN NAME_LEN + 15
#define FIREFOX "/usr/bin/firefox"
void make_route_url(char *url, gpscoords *pos, gpscoords *target) {
char pos_sign_n;
char pos_sign_e;
char tar_sign_n;
char tar_sign_e;
pos_sign_n = pos->north ? '+' : '-';
pos_sign_e = pos->east ? '+' : '-';
tar_sign_n = target->north ? '+' : '-';
tar_sign_e = target->east ? '+' : '-';
sprintf(url,
"http://map.project-osrm.org/?z=13&loc=%c%u.%u,%c%u.%u&loc=%c%u.%u,%c%u.%u",
pos_sign_n, pos->lat, pos->lat_frac,
pos_sign_e, pos->lon, pos->lon_frac,
tar_sign_n, target->lat, target->lat_frac,
tar_sign_e, target->lon, target->lon_frac);
}
void show_route(gpscoords *pos, gpscoords *target) {
// char url[75];
fprintf(stderr, "show_route not implemented!\n");
exit(-1);
}
int run_client(char *name, char *serverip) {
char *cmdline;
size_t line_len;
char cmd[11];
gpsinfo info;
gpscoords pos, targetpos;
char targetname[NAME_LEN];
bzero(targetname, NAME_LEN);
bzero(&info, sizeof(info));
bzero(&pos, sizeof(pos));
bzero(&targetpos, sizeof(targetpos));
if (register_client(serverip, name, &info) == -1) {
perror("Error registering client.");
return -1;
}
find_self(&pos);
if (update_position(&info, &pos) == -1) {
printf("Failed to send initial position to server.\n");
exit(-1);
}
for (;;) {
printf("Command: ");
line_len = 0;
cmdline = NULL;
getline(&cmdline, &line_len, stdin);
if (strncmp(cmdline, "update", 3) == 0) {
find_self(&pos);
if (update_position(&info, &pos) == -1) {
printf("Failed to update.\n");
}
} else if (strncmp(cmdline, "find", 3) == 0) {
sscanf(cmdline, "%10s %25s", cmd, targetname);
if (get_position(&info, targetname, &targetpos) == -1) {
printf("Couldn't find target.\n");
} else {
show_route(&pos, &targetpos);
}
} else if (strncmp(cmdline, "quit", 4) == 0) {
free(cmdline);
break;
}
free(cmdline);
}
if (unregister_client(&info) == -1) {
perror("Error unregistering client.");
return -1;
}
return 0;
}
int main(int argc, char **argv) {
if (argc < 2) {
printf("Usage: ./client <client name> <server_ip>\n");
return 0;
}
return run_client(argv[1], argv[2]);
}
socket.c
#include <sys/socket.h>
#include <stdint.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include "sockets.h"
int create_dg_socket(in_port_t port) {
// Create the socket
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1) {
printf("create_dg_socket cannot create socket!");
return -1;
}
// Bind the socket port
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
printf("create_dg_socket cannot bind socket!");
close(sockfd);
return -1;
}
return sockfd;
}
int open_dg_socket(char *ipaddr, in_port_t port, struct sockaddr_in *addr) {
// Create the socket
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1) {
return -1;
}
// Setup
addr->sin_family = AF_INET;
addr->sin_port = htons(port);
addr->sin_addr.s_addr = inet_addr(ipaddr);
return sockfd;
}
int dg_sendrecv(int sockfd,
struct sockaddr_in *addr,
char *message, size_t out_len,
char *response, size_t in_len) {
if (sendto(sockfd, message, out_len, 0, (struct sockaddr *)&addr, sizeof(*addr)) == -1) {
printf("dg_sendrecv cannot send data!");
return -1;
}
int ret = recvfrom(sockfd, response, in_len, 0, NULL, NULL);
if (ret == -1) {
printf("dg_sendrecv cannot read data!");
return -1;
}
return ret;
}
/*
int dg_sendrecv(int sockfd,
struct sockaddr_in *addr,
char *message, size_t out_len,
char *response, size_t in_len) {
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(ipaddr);
return dg_sendrecv_addr(sockfd, &addr, message, out_len, response, in_len);
}
*/
server.c
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include "sockets.h"
#include "gps.h"
#include "server.h"
#define NUM_CLIENTS 5
char clients[NUM_CLIENTS][NAME_LEN];
gpscoords coords[NUM_CLIENTS];
void do_register(int sockfd, struct sockaddr_in *clientaddr) {
char msg[REGISTER_CMD_LEN];
char *name;
unsigned char id, i;
if (recv(sockfd, msg, REGISTER_CMD_LEN, 0) == -1) {
perror("Error receiving register command.");
exit(-1);
}
// first byte is server command, rest is name
name = &msg[1];
id = NO_RES;
for (i = 0; i < NUM_CLIENTS; ++i) {
if (clients[i][0] == '\0') {
strncpy(clients[i], name, NAME_LEN);
clients[i][NAME_LEN - 1] = '\0';
bzero(&coords[i], sizeof(coords[i]));
id = i + 1;
break;
}
}
if (sendto(sockfd,
&id, sizeof(id),
0,
(struct sockaddr *)clientaddr, sizeof(*clientaddr)) == -1) {
perror("Error replying to client.");
exit(-1);
}
}
void do_unregister(int sockfd, struct sockaddr_in *clientaddr) {
unsigned char msg[UNREGISTER_CMD_LEN];
unsigned char id;
char res = NO_RES;
if (recv(sockfd, &msg, UNREGISTER_CMD_LEN, 0) == -1) {
perror("Error receiving unregister command.");
exit(-1);
}
id = msg[1] - 1;
if (id < NUM_CLIENTS) {
clients[id][0] = '\0';
res = SUCC_RES;
}
if (sendto(sockfd,
&res, sizeof(res),
0,
(struct sockaddr *)clientaddr, sizeof(*clientaddr)) == -1) {
perror("Error responding to client.");
exit(-1);
}
}
int update_client(unsigned char id, gpscoords *pos) {
id -= 1;
if (id >= NUM_CLIENTS)
return -1;
memcpy(&coords[id], pos, sizeof(coords[id]));
return 0;
}
void do_update(int sockfd, struct sockaddr_in *clientaddr) {
/**
* Receive an update message over the socket and unpack the
* data. Then use the update_client function to update the server's
* internal representation of the client co-ordinates. Then respond to the
* client with the required value.
* Use recv to read the full message (of length UPDATE_CMD_LEN) into buffer.
* Unpack data, message of following format:
* U<id><fields of gpscoords>
* Character 'U' (meaning update), followed by ID of the client (unsigned char)
* and then the gpscoord structure in network format.
*
* 1. Unpack ID
* 2. Unpack coordinates with (int update_client(unsigned char id, gpscoords *pos)
* which takes ID and pointer to position struct, returns -1 on error and 0 on success
* Server should then respond to client using sendto function and reply
* NO_RES on error and SUCC_RES on success.
*/
char msg[UPDATE_CMD_LEN];
recv(sockfd, msg, UPDATE_CMD_LEN, flags);
fprintf(stderr, "do_update not implemented!\n");
exit(-1);
}
static gpscoords *get_client(char *name) {
for (int i = 0; i < NUM_CLIENTS; ++i) {
if (strcmp(name, clients[i]) == 0) {
return &coords[i];
break;
}
}
return NULL;
}
void do_get(int sockfd, struct sockaddr_in *clientaddr) {
char msg[GET_CMD_LEN];
char res[GET_RES_LEN];
char *name;
if (recv(sockfd, msg, GET_CMD_LEN, 0) == -1) {
perror("Error receiving get command.");
exit(-1);
}
name = &msg[1];
name[NAME_LEN - 1] = '\0';
gpscoords *pos = get_client(name);
if (pos == NULL) {
res[0] = NO_RES;
} else {
res[0] = SUCC_RES;
pack_gpscoords(pos, &res[1]);
}
if (sendto(sockfd,
&res, GET_RES_LEN,
0,
(struct sockaddr *)clientaddr, sizeof(*clientaddr)) == -1) {
perror("Error sending result to client.");
exit(-1);
}
}
int serve(int sockfd) {
char cmd;
struct sockaddr_in clientaddr;
socklen_t clientaddrlen = sizeof(clientaddr);
for (;;) {
if (recvfrom(sockfd,
&cmd, sizeof(cmd),
MSG_PEEK,
(struct sockaddr *)&clientaddr, &clientaddrlen) == -1) {
exit(-1);
}
switch (cmd) {
case CMD_REGISTER:
do_register(sockfd, &clientaddr);
break;
case CMD_UNREGISTER:
do_unregister(sockfd, &clientaddr);
break;
case CMD_UPDATE:
do_update(sockfd, &clientaddr);
break;
case CMD_GET:
do_get(sockfd, &clientaddr);
break;
default:
break;
}
}
}
void init_info() {
int i;
for (i = 0; i < NUM_CLIENTS; ++i) {
clients[i][0] = '\0';
}
}
int main(int argc, char **argv) {
int sockfd = create_dg_socket(SERVER_PORT);
if (sockfd == -1) {
fprintf(stderr, "Error creating socket!\n");
return -1;
}
init_info();
printf("Server ready.\n");
serve(sockfd);
// Note: server never terminates, we're relying on the system to clean up
// our open socket file descriptor (and shut it down)
return 0;
}
If you are looking for a way to safe and read data from char arrays that maybe will help you:
char buffer[5+sizeof(gpscoords)];
int *int_pointer;
gpscoords *gps_pointer;
int id=1;
gpscoords gps="some gps contend";
int id_frombuffer;
gpscoords gps_frombuffer;
char c_frombuffer;
buffer[0]='U';
int_pointer=(int*)&buffer;
int_pointer+=1;
*int_pointer=id;
gps_pointer=(gpscoords*)&buffer;
gps_pointer+=5;
*gpspointer=gps;
//send buffer
c_frombuffer=buffer[0];//c_frombuffer now contains 'U'
int_pointer=(int*)&buffer;
int_pointer+=1;
id_frombuffer=*int_pointer;//id_frombuffer now contains 1
gps_pointer=(gpscoords*)&buffer;
gpscoords+=5;
gps_frombuffer=*pointer;//gps_frombuffer now contains "some gps contend"
As an example if your client code looks like that:
void sendupdate(unsigned char id,gpscoords gps)
{
char buffer[2+sizeof(gpscoords)];
gpscoords *gps_pointer;
buffer[0]='U';
buffer[1]=id;
gps_pointer=(gpscoords*)&buffer;
gps_pointer+=2;
*gpspointer=gps;
send(socket, buffer, 2+sizeof(gpscoords), flags);
}
your server function should look like that:
void do_update(int sockfd, struct sockaddr_in *clientaddr)
{
char buffer[2+sizeof(gpscoords)];
recv(sockfd, buffer, 2+sizeof(gpscoords), flags);
unsigned char id_frombuffer=buffer[1];
gpscoords *gpspointer=(gpscoords*)&buffer;
gpspointer+=2;
update_client(id_frombuffer, gpspointer);
}

variable length message over tcp

I am trying to send variable length message in TCP but the message length that
is printed is always 0. I am using beej guide code for send and receive and pack and unpack to send the header length.Can someone please point out the mistake.
server code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MAX_SIZE 50
void error(const char *msg)
{
perror(msg);
exit(1);
}
void packi32(unsigned char *buf, unsigned long i)//from beej guide
{
*buf++ = i>>24; *buf++ = i>>16;
*buf++ = i>>8; *buf++ = i;
}
/* sends all data - thanks to Beej's Guide to Network Programming */
int sendall(int s, char *buf, int *len)
{
int total=0;
int bytesleft=*len;
int n=0;
/* send all the data */
while(total<*len){
/* send some data */
n=send(s,buf+total,bytesleft,0);
/* break on error */
if(n==-1)
break;
/* apply bytes we sent */
total+=n;
bytesleft-=n;
}
/* return number of bytes actually send here */
*len=total;
/* return -1 on failure, 0 on success */
return n==-1?-1:0;
}
int sendus(int s,char *msg)
{
char buf[4];//here 4 is header length
int len = strlen(msg);
packi32(buf,len);
int ll = 4;// ll is header length containing message length
int x;
if((x = sendall(s,buf,&ll))< 0)
printf("value of sent x %d\n",x);
int y = sendall(s,msg,&len);
return y;
}
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");
char msg[1024] = "hello";
int xx = sendus(sockfd,(char*)msg);
close(newsockfd);
close(sockfd);
return 0;
}
client code
#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>
#include<errno.h>
void error(const char *msg)
{
perror(msg);
exit(0);
}
/** unpacki32() -- unpack a 32-bit int from a char buffer (like ntohl())
*/
unsigned long unpacki32(unsigned char *buf)
{
return (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
}
/* receives all data - modelled after sendall() */
int recvall(int s, char *buf, int *len, int timeout){
int total=0;
int bytesleft=*len;
int n=0;
time_t start_time;
time_t current_time;
/* clear the receive buffer */
bzero(buf,*len);
time(&start_time);
/* receive all data */
while(total<*len){
/* receive some data */
n=recv(s,buf+total,bytesleft,0);
/* no data has arrived yet (non-blocking socket) */
if(n==-1 && errno==EAGAIN){
time(&current_time);
if(current_time-start_time>timeout)
break;
sleep(1);
continue;
}
/* receive error or client disconnect */
else if(n<=0)
break;
/* apply bytes we received */
total+=n;
bytesleft-=n;
}
/* return number of bytes actually received here */
*len=total;
/* return <=0 on failure, bytes received on success */
return (n<=0)?n:total;
}
int recvme(int s, char *buf)
{
char len[4];
int l = 4;
int n = recvall(s,len,&l,10);
int msg_len = unpacki32(len);
printf("msg_length :%d",msg_len);
int z ;
z = recvall(s,buf,&msg_len,10);
return z;
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[1024];
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");
n = recvme(sockfd, buffer);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
close(sockfd);
return 0;
}
The basic cause for the failure is in the server's line
int xx = sendus(sockfd,(char*)msg);
- sockfd is the listen() socket, but we have to use the newsockfd returned from accept(), i. e.
sendus(newsockfd, msg);

segmentation fault when using gethostbyname

I am trying to create a proxy server which accepts requests from client and sends the response back to client after receiving message from the server.
But the program gives segmentation fault.
My code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
int main(int argc,char *argv[])
{
struct sockaddr_in server,client;
struct hostent *host;
int s1,s2,s3,len;
int port;
char ip[100];
char path[100];
int p;
int n;
char buffer[500];
char site[500];
port = atoi(argv[1]);
bzero((char *)&server,sizeof(server));
server.sin_port = htons(port);
server.sin_addr.s_addr = INADDR_ANY;
server.sin_family = AF_INET;
s1 = socket(AF_INET,SOCK_STREAM,0);
if(bind(s1,(struct sockaddr *)&server,sizeof(server)) == -1) {
perror("can't bind");
exit(1);
}
if(listen(s1,10) == -1) {
perror("coudnt't listen");
exit(1);
}
len = sizeof(client);
s2 = accept(s1,(struct sockaddr *)&client,&len);
if(s2 == -1) {
perror("coudnt aceept");
exit(1);
}
memset(buffer,0,sizeof(buffer));
n = recv(s2,buffer,500,0);
if(n < 0) {
perror("not recieved");
exit(1);
}
sscanf(buffer, "http://%99[^:]:%99d/%99[^\n]", ip, &p, path);
bzero((char *)&client,sizeof(client));
client.sin_port = htons(80);
host = gethostbyname(ip);
bcopy((char *)host->h_addr,(char *)&client.sin_addr.s_addr,host->h_length);
client.sin_family = AF_INET;
s3 = socket(AF_INET,SOCK_STREAM,0);
if(connect(s3,(struct sockaddr *)&client,sizeof(client)) == -1) {
perror("can't connect\n");
exit(1);
}
sprintf(site,"GET http://%s/ HTTP/1.0\n\n",ip);
n = send(s3,site,strlen(site),0);
if(n < 0) {
perror("message not sent");
exit(1);
}
while(1) {
memset(site,0,sizeof(site));
n = recv(s3,site,500,0);
if(n < 0) {
perror("coudnot read");
exit(1);
}
site[n] = '\0';
send(s2,site,strlen(site),0);
}
close(s1);
close(s2);
return 0;
}
The mistake seems to be coming from gethostbyname(ip) because when I use gethostbyname("www.iiita.ac.in"), it works.
gethostbyname returns a null pointer in case of error and, thus, host->h_addr is a null dereference.
You need to check whether host is NULL or not before using it.
See http://man7.org/linux/man-pages/man3/gethostbyname.3.html

Resources