int main( int argc, char *argv[] ){ int sockfd, cfd, rec, s, wr=0, sent, lenn; int start = 0; char pcBuf[MAXBUF]; char fulBuf[MAXBUF]; int received; struct sockaddr client_addr; struct addrinfo hints; struct addrinfo *res; socklen_t client_addr_size; /******************* Connect to Client *******************/ /* struct setup*/ hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; s = getaddrinfo(NULL, argv[1], &hints, &res); if( s!=0){ fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); exit(EXIT_FAILURE); } /* create socket */ sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if( sockfd == -1) handle_error("socket"); /* bind the socket */ if( bind(sockfd, res->ai_addr, res->ai_addrlen) == -1) handle_error("bind"); /* listen for client */ if( listen(sockfd, LISTEN_BACKLOG) == -1) handle_error("listen"); freeaddrinfo(res); /* accept connection */ /* int accept(int sockfd, struct sockaddr *addr, socketlen_t *addrlen) */ client_addr_size = sizeof(struct sockaddr); while(1){ cfd = accept( sockfd, (struct sockaddr *) &client_addr, &client_addr_size); if( cfd <= 0) handle_error("accept"); /*receive GET request from client */ received= recv(cfd, pcBuf, MAXBUF, 0); int recc= recv(cfd, pcBuf+received, MAXBUF, 0); if(received == -1) fprintf(stderr, "recv: failed"); /*print received GET request on server terminal*/ if(write(1, pcBuf, received+recc) == -1){ handle_error("write"); } /* echo what was received from the client */ if((sent = send(cfd,pcBuf, received, 0)) <0) handle_error("send"); /******************* Parse Request From Client *******************/ int len = strlen(pcBuf); struct ParsedRequest *req = ParsedRequest_create(); if(ParsedRequest_parse(req, pcBuf, len) <0) { printf("parse failed\n"); return -1; } char *h = req->host; char *p = req->path; get(h, p, cfd); close(cfd); }/* end infinite loop */ /* Clean up */ close(sockfd); return 0; } /* end main */
int main(int argc, char **argv) { char *port; // port int sockfd, new_fd; // listen on sock_fd, new connection on new_fd struct addrinfo hints, *servinfo, *p; struct sockaddr_storage their_addr; // connector's address information socklen_t sin_size; struct sigaction sa; int yes=1; char s[INET6_ADDRSTRLEN]; int rv; // received data char buf[MAXDATASIZE]; int numbytes; // parsed request struct ParsedRequest *req; // response char header[MAXDATASIZE]; int numHead; // file FILE *fp; char *fType; if (argc != 2) { printf("Usage: http_server <port-number>\n"); exit(1); } port = argv[1]; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; // use my IP if ((rv = getaddrinfo(NULL, port, &hints, &servinfo)) != 0) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); return 1; } // loop through all the results and bind to the first we can for(p = servinfo; p != NULL; p = p->ai_next) { if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { perror("server: socket"); continue; } if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { perror("setsockopt"); exit(1); } if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) { close(sockfd); perror("server: bind"); continue; } break; } freeaddrinfo(servinfo); // all done with this structure if (p == NULL) { fprintf(stderr, "server: failed to bind\n"); exit(1); } if (listen(sockfd, BACKLOG) == -1) { perror("listen"); exit(1); } sa.sa_handler = sigchld_handler; // reap all dead processes sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; if (sigaction(SIGCHLD, &sa, NULL) == -1) { perror("sigaction"); exit(1); } while(1) { // main accept() loop sin_size = sizeof their_addr; new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size); if (new_fd == -1) { perror("accept"); continue; } inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), s, sizeof s); if (!fork()) { // this is the child process close(sockfd); // child doesn't need the listener if((numbytes = recv(new_fd, buf, MAXDATASIZE-1, 0)) == -1) { perror("recv"); exit(1); } strcpy(buf + numbytes, "\r\n\0"); // make it version 1.0, just for testing char *version = strstr(buf, "HTTP/1.1"); if (version > 0) strncpy(version + 7, "0", 1); int len = strlen(buf); req = ParsedRequest_create(); int retval = ParsedRequest_parse_server(req, buf, len); if (retval < -1) { getResponse(header, "501 Not Implemented", TYPE_HTML, notImpMsg); sendResponse(new_fd, header); } else if (retval < 0) { // 400 Bad Request getResponse(header, "400 Bad Request", TYPE_HTML, badReqMsg); sendResponse(new_fd, header); } // use buf as a temporary buffer to get the path getPath(buf, req->path); fType = getType(buf); if (fType == NULL) { // Unsupported file type [trumps file not found; respond w/400 bad request.] getResponse(header, "400 Bad Request", TYPE_HTML, badReqMsg); sendResponse(new_fd, header); } fp = fopen(buf, "rb"); if (fp == NULL) { // File not found getResponse(header, "404 Not Found", TYPE_HTML, notFoundMsg); sendResponse(new_fd, header); } fseek(fp, 0, SEEK_END); long fsize = ftell(fp); fseek(fp, 0, SEEK_SET); // Send headers numHead = 0; numHead += sprintf(header, "HTTP/1.0 200 OK\r\n"); numHead += sprintf(header + numHead, "Connection: close\r\n"); numHead += sprintf(header + numHead, "Content-Length: %lu\r\n", fsize); numHead += sprintf(header + numHead, "Content-Type: %s\r\n\r\n", fType); if (send(new_fd, header, strlen(header), 0) == -1) perror("send"); // Send body long chunk; while (fsize > 0) { chunk = fsize < MAXDATASIZE ? fsize : MAXDATASIZE ; fread(buf, 1, chunk, fp); send(new_fd, buf, chunk, 0); fsize -= chunk; } close(new_fd); ParsedRequest_destroy(req); exit(0); } close(new_fd); // parent doesn't need this } return 0; }