// CREDITS : F. Harrouet, www.enib.fr/~harrouet //====================================================================== #include "main.h" #include "httpServerLib.h" #define BUFFER_SIZE 0x1000 //====================================================================== void * dialogThread(void *arg) { pthread_detach(pthread_self()); char buffer[BUFFER_SIZE]; Request *req=(Request *)arg; //---- receive and analyse HTTP request line by line ---- bool first=true; for(;;) { if(recvLine(req->sock,buffer,BUFFER_SIZE)<=0) { break; } printf("%s",buffer); if(first) { first=false; sscanf(buffer,"%s %s",req->requestMethod,req->requestUri); } else if(!strcmp(buffer,"\n")||!strcmp(buffer,"\r\n")) { break; } } //---- prepare and send HTTP reply ---- int r=sprintf(buffer,"HTTP/1.0 200 OK\n" "Connection: close\n" "Content-Type: text/html\n" "\n" "\n" // Text displayed in the web browser : "200 - OK
\n" "method: %s
\n" "uri: %s
\n" "hello world\n" "\n", req->requestMethod, req->requestUri); sendAll(req->sock,buffer,r); destroyRequest(req); return (void *)0; } //====================================================================== // MAIN //====================================================================== int main(int argc, char **argv) { //---- avoid exiting on broken client connection (ignore SIGPIPE) ---- struct sigaction sa; memset(&sa,0,sizeof(struct sigaction)); sa.sa_handler=SIG_IGN; if(sigaction(SIGPIPE,&sa,(struct sigaction *)0)==-1) { perror("sigaction"); exit(1); } //---- check command line arguments ---- if(argc!=2) { fprintf(stderr,"usage: %s http_port\n",argv[0]); exit(1); } //---- extract local port number ---- int httpPortNumber; if(sscanf(argv[1],"%d",&httpPortNumber)!=1) { fprintf(stderr,"invalid port %s\n",argv[1]); exit(1); } //---- multithreaded TCP server launching dialogThread() ---- //---- create HTTP listen socket ---- int httpSocket=socket(PF_INET,SOCK_STREAM,0); if(httpSocket==-1) { perror("socket"); exit(1); } // ... avoiding timewait problems (optional) int on=1; if(setsockopt(httpSocket,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(int))==-1) { perror("setsockopt"); exit(1); } // ... bound to any local address on the specified port struct sockaddr_in myAddr; myAddr.sin_family=AF_INET; myAddr.sin_port=htons(httpPortNumber); myAddr.sin_addr.s_addr=htonl(INADDR_ANY); if(bind(httpSocket,(struct sockaddr *)&myAddr,sizeof(myAddr))==-1) { perror("bind"); exit(1); } // ... listening connections if(listen(httpSocket,10)==-1) { perror("listen"); exit(1); } for(;;) { //---- accept new HTTP connection ---- struct sockaddr_in fromAddr; socklen_t len=sizeof(fromAddr); int dialogSocket=accept(httpSocket,(struct sockaddr *)&fromAddr,&len); if(dialogSocket==-1) { perror("accept"); exit(1); } printf("new HTTP connection from %s:%d\n", inet_ntoa(fromAddr.sin_addr),ntohs(fromAddr.sin_port)); //---- start a new dialog thread ---- pthread_t th; if(pthread_create(&th,(pthread_attr_t *)0, dialogThread,createRequest(dialogSocket))) { fprintf(stderr,"cannot create thread\n"); exit(1); } } close(httpSocket); return 0; } //^^^^^^^^^^^^^^^^^^^^^^^^^^ EOF ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^