#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <fcntl.h>
#define SERV_TCP_PORT 8080
#define BUFSIZE  32*1024
#define XSIZE  BUFSIZE*50

void tcpserver_read( int s );
void tcpserver_write( int s );

main(int argc, char *argv[])
{
 static char buf[BUFSIZE];
 static char hostname[64];
 struct hostent *hp;
 struct sockaddr_in saddr, caddr;
 int  sendbuff, recvbuff, tmp, clen;
 int  s, connected_socket, childpid;

 if ( argc == 2 )
  strcpy( hostname, argv[1] );
 else
  gethostname( hostname, sizeof( hostname ) );
 printf("hostname is %s\n", hostname);
 if (( hp = gethostbyname(hostname)) == NULL) {
  fprintf( stderr, "%s: host unknown.\n",hostname);
  exit(1);
 }
 if(( s = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0) {
  fprintf( stderr, "%s: host unknown.\n",hostname);
  exit(1);
 }

 sendbuff = BUFSIZE;
 if( setsockopt( s, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof( sendbuff ) ) < 0) {
  fprintf( stderr, "server: setsockopt SO_SNDBUF");
  exit(1);
 }

 recvbuff = BUFSIZE;
 if( setsockopt( s, SOL_SOCKET, SO_RCVBUF, &recvbuff, sizeof( recvbuff ) ) < 0) {
  fprintf( stderr, "server: setsockopt SO_RCVBUF");
  exit(1);
 }

 getsockopt( s, SOL_SOCKET, SO_SNDBUF, &sendbuff, &tmp );
 getsockopt( s, SOL_SOCKET, SO_RCVBUF, &recvbuff, &tmp );

 bzero( (char*) &saddr, sizeof( saddr ) );
 saddr.sin_family = AF_INET;
 saddr.sin_addr.s_addr = htonl( INADDR_ANY );
 saddr.sin_port = htons( SERV_TCP_PORT );
 if( bind( s, (struct sockaddr *) &saddr, sizeof( saddr ) ) < 0) {
  fprintf( stderr,"server can't bind local address\n");
  exit(1);
 }
 listen( s, 5 );
 for (;;) {
  clen  = sizeof( caddr );
  connected_socket = accept( s, (struct sockaddr *) &caddr, &clen );
  printf( "caddr : %s \n", inet_ntoa( caddr.sin_addr ) );

  if( connected_socket < 0 ) {
   fprintf( stderr, "error acceptting\n");
   exit( 1 );
  }
  if( ( childpid = fork() ) < 0 ) {
   fprintf( stderr, "error forking\n");
   exit( 1 );
  }
  else if ( childpid == 0 ) {  
   close( s );
   tcpserver_read( connected_socket );
   tcpserver_write( connected_socket );
   exit( 0 );
  }
  close( connected_socket );
 }
 if( close( s ) < 0 ){
  fprintf( stderr, "close" );
  exit(1);
 }
 return( 0 );
}
void tcpserver_read( int s )
{
 int  n;
 char read_buf[ BUFSIZE ];
 n = read( s, read_buf, BUFSIZE );
 write( 1, read_buf, strlen( read_buf ) );    
 printf( "%c%c\n",read_buf[4], read_buf[5] );
 return; 
}
void tcpserver_write( int s )
{
 char write_buf[ BUFSIZE ];
 sprintf( write_buf, "HTTP/1.1 200 OK\n" );
 write( s, write_buf, strlen( write_buf ) );
 write( 1, write_buf, strlen( write_buf ) );    

 sprintf( write_buf, "Server: TEST/0.01\n");
 write( s, write_buf, strlen( write_buf ) );
 write( 1, write_buf, strlen( write_buf ) );    

 sprintf( write_buf, "Pragma: no-cache\n");
 write( s, write_buf, strlen( write_buf ) );
 write( 1, write_buf, strlen( write_buf ) );    

 sprintf( write_buf, "Cache-Control: no-cache\n");
 write( s, write_buf, strlen( write_buf ) );
 write( 1, write_buf, strlen( write_buf ) );    

 sprintf( write_buf, "Content-Type: text/html\n");
 write( s, write_buf, strlen( write_buf) );
 write( 1, write_buf, strlen( write_buf) );    

 sprintf( write_buf, "Connection: close\n");
 write( s, write_buf, strlen( write_buf ) );
 write( 1, write_buf, strlen( write_buf ) );    

 sprintf( write_buf, "\n\n");
 write( s, write_buf, strlen( write_buf) );
 write( 1, write_buf, strlen( write_buf) );    

 sprintf( write_buf, "TEST \n" );
 write( s, write_buf, strlen( write_buf ));
 write( 1, write_buf, strlen( write_buf ));    
 return;   
}