[prog] socket programming with C language

Conor Daly c.daly at met.ie
Thu Oct 3 09:34:28 EST 2002


On Tue, Oct 01, 2002 at 02:00:52AM -0700 or thereabouts, Abel Pires da Silva wrote:
> Dear all, 
> I'm writing a simple program just like proxy (complete
> program attached),
> that try to reject connection if there is any match
> between the host name 
> requested by browser and the list of addresses stored
> in file tabel.txt.
> 
> I read() a socket descriptor, wich store the reading
> result in buffer,
> and I now that its content is like below:
> 
> GET / HTTP/1.0
> Connection: Keep-Alive
> User-Agent: Mozilla/4.75 [en] (X11; U; Linux
> 2.2.17-21mdk i686)
> Host: localhost:8000
> Accept: image/gif, image/x-xbitmap, image/jpeg,
> image/pjpeg, image/png, */*
> Accept-Encoding: gzip
> Accept-Language: en
> Accept-Charset: iso-8859-1,*,utf-8
> 
> I'm trying to do is to make string comparation between
> the *HOST (at line four)
> with the addresses stored in file tabel.txt
> 
> Any suggestion to do the comparation?
> I'm running this on Linux machine 2.2.17-21 mdk i686.
> 
> Please help...
> 
> Regards,
Abel,

I'm not familiar with either socket programming or threading so some of what
I say below may be wrong.  You appear to have the program almost complete in
any case but I've suggested a few changes.

Conor

> Content-Description: Program.txt
> #include <sys/types.h>
> #include <sys/socket.h>
> #include <netinet/in.h>
> #include <arpa/inet.h>
> #include <netdb.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <string.h>
> #include <signal.h>
> #include <sys/stat.h>
> #include <ctype.h>
> #include <fcntl.h>
> 
> #define MAXBUF 65535 
> #define MAXLINE 65535
> #define SERV_ADDR "127.0.0.1"
> #define SERV_PORT 80 
> #define BACKLOG 20
> 
> main (int argc, char *argv [])
> {
> 
> char buffer [MAXBUF];
> char line [MAXLINE];
> char cliline [80];
> int port, rd, socket_fd, socket_fd2, socket_fd3;
> socklen_t serv_len;
> struct sockaddr_in server, client;
> FILE *PF;
> 
> if (argc != 2)
>  	{
> 	printf ("usage: %s <port>\n", argv[0]);
> 	exit(1);
> 	}
> port = atoi (argv[1]);
> 
> if ((socket_fd=socket (PF_INET, SOCK_STREAM, 0))<0)
> 	{
> 	printf ("%s: cannot create socket!\n", argv[0]);
> 	exit(1);
> 	}
> bzero ((char *)&server, sizeof(server));
> server.sin_family = AF_INET;
> server.sin_addr.s_addr = htonl (INADDR_ANY);
> server.sin_port = htons (port);
> 
> if (bind (socket_fd, (struct sockaddr *)&server, sizeof (server))<0)
> 	{
> 	printf ("%s: cannot bind socket!\n", argv [0], port);
> 	exit (1);
> 	}
> 
> listen (socket_fd, BACKLOG);
> 
> signal (SIGCHLD, SIG_IGN);
> 
> serv_len =  sizeof (server);
> 
> if (fork()) exit (0);
> 
> for (;;)
> {
> 
> if ((socket_fd2 = accept (socket_fd, (struct sockaddr *)&server, &serv_len))<0)
> 	{
> 	printf ("%s: cannot accept!\n", argv[0]);
> 	break;
> 	}
> 
> if (fork() !=0)
> {
> close (socket_fd2);
> continue;
> }
> 
> else {
> 
> if (fork() == 0)
> {
> 

You appear to be starting an infinite loop here.  Is that required or could
you do something like

while ((fgets(cliline,20, buffer))!= NULL)

below the "read (socket" line.  It appears that you accept a socket
connection above and then fork to handle that connection.  On that basis,
you shouldn't need to keep looping over that socket and loading it into
"buffer"

> while (1)
> {
> nextline:
> memset (buffer, 0, MAXBUF);
> 	if ((rd = read (socket_fd2, buffer, MAXBUF))<0)
> 		{
> 		printf ("%s: cannot read socket_fd2!\n", argv[0]);
> 		break;
> 		}
> 
> 	/* at this stage, I need to retrieve the fourth line of the message sent by
> 	 * browser..and store the line in cliline */

something like:

while ((fgets(cliline,20, buffer))!= NULL)
/* read a line at a time from "buffer" */
{
 if((strstr(cliline, "Host:" ))!=0) break; /* Look for a match with "Host:"
						and exit the loop*/ 
}


Now, do you need to load the restricted address file from disk for each
connection?  You might do better to create an array of restricted addresses
in memory at the start of the program before any fork() happens.  That way
you only load the address list once.  If you do that, you would need to trap
a signal to _reload_ the address list if it gets changed...  That _could_ be
done by simply killing and restarting the program.

Whichever way you choose to do this, the loop below is much the same.  If
the address list is in memory, the "while((fgets" line needs to change to
something like:

for(some loop condition) {
strncpy(line, listarray[index], 20);

> if ((PF=fopen("tabel.txt", "r"))!= 0)  /* open the file contained with restricted addresses */
> 	{
> 	while ((fgets(line,20, PF))!= NULL)
> 	/* gets list of restricted addresses from file table.txt */
> 		{
> 	if((strstr(line, cliline))!=0) /* deny if any match*/
> 			{
> 			/*deny connection */
> 			write (socket_fd2, "<BODY><PRE>\n", 12);
> 			write (socket_fd2, "ERROR 401: ACCESS DENIED!\n", 26);
>   			write (socket_fd2," </PRE></BODY></HTML>\n", 22);

I'd move both "fclose(PF);" lines to the end of the "if(fopen" construct and
get rid of the "goto nextline;".  Instead, do something like

			error=401;
			break;

> 			fclose (PF);
> 			goto nextline;
> 			}
> 		}
> 	fclose (PF);
> 	}
> 

And check the value of "error" here to decide if your go on...

if ( error == 401 ) 
{
/* do socket cleanup stuff here */
exit(1);
}

> /* continue if there is no macth */
> 
> bzero ((char *)&client, sizeof (client));
> client.sin_family = AF_INET;
> client.sin_addr.s_addr = inet_addr (SERV_ADDR); /* connect to localhost only.. */
> client.sin_port = htons (SERV_PORT);
> 
> if ((socket_fd3 = socket (AF_INET, SOCK_STREAM, 0)) < 0)
> 	{
> 	printf ("%s: cannot create socket to connect!\n", argv[0]);
> 	continue;
> 	}
> if (connect (socket_fd3, (struct sockaddr *)&client, sizeof (client))<0)
> 	{
> 	printf ("%s: cannot connect to server!\n", argv[0]);
> 	break;
> 	}
> 
> write (socket_fd3, buffer, rd );  /* continue to server_socket if nothing match*/
> 
> memset (buffer, 0, MAXBUF);
> if ((rd = read (socket_fd3, buffer, MAXBUF))<0)
> 	{
> 	printf ("%s: cannot read from socket_fd3!\n", argv [0]);
> 	break;
> 	}
> 
> write (socket_fd2, buffer, rd);
> 
> } /* while loop */
> close (socket_fd3);
> close (socket_fd2);
> } /* child */
> } /* else */
> } /* loop forever */
> close (socket_fd);
> } /* main loop */


-- 
Conor Daly 
Met Eireann, Glasnevin Hill, Dublin 9, Ireland
Ph +353 1 8064276 Fax +353 1 8064247
------------------------------------
bofh.irmet.ie running RedHat Linux  8:55am  up 5 days, 16:05, 11 users,  load average: 0.01, 0.06, 0.19


**********************************************************************
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom they
are addressed. If you have received this email in error please notify
the system manager.

This footnote also confirms that this email message has been swept 
for the presence of computer viruses.


**********************************************************************




More information about the Programming mailing list