/* * SendToWeb.c - Web Server - Socket Programming Example * Written by Pejman Moghadam - 2011-12-16 * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * pmoghadam_a@t_yahooo wrote this file. As long as you retain this notice you * can do whatever you want with this stuff. If we meet some day, and you think * this stuff is worth it, you can buy me a beer in return Pejman Moghadam * ---------------------------------------------------------------------------- * * Change Log: * * Wed Jun 26 10:42:10 IRDT 2013 * Content-Length added to HTTP response * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define BUFSIZE 8096 #define BACKLOG 1 /* pending connections queue length */ #define PORT "8181" int main(int argc, char **argv) { int i, len, status, listen_fd, accept_fd, file_fd, yes = 1; off_t file_size; struct stat file_st; socklen_t addr_size; char buffer[BUFSIZE+1]; char *me = basename(argv[0]); char *filename = basename(argv[1]); char *file_addr = argv[1]; struct addrinfo hints, *servinfo; /* Static variables will fill with zeros */ static struct sockaddr_storage client_addr; /* Check syntax */ if (argc < 2) { fprintf(stderr, "Usage:\n %s \n", me); exit(1); } /* Open the file for reading */ file_fd = open(file_addr, O_RDONLY); if(file_fd == -1) { fprintf(stderr, "Can not open file: %s", file_addr); exit(1); } /* Find out file size */ fstat(file_fd, &file_st); file_size = file_st.st_size; /* Load up address structs */ memset(&hints, 0, sizeof hints); /* make sure the struct is empty */ hints.ai_family = AF_INET; /* use IPv4 */ hints.ai_socktype = SOCK_STREAM; /* TCP stream sockets */ hints.ai_flags = AI_PASSIVE; /* fill in my IP */ status = getaddrinfo(NULL, PORT, &hints, &servinfo); if(status != 0) { fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status)); exit(1); } /* Setup a network socket */ listen_fd = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol); if(listen_fd == -1) { perror("socket error: "); exit(1); } /* if port is in the TIME_WAIT state, go ahead and reuse it anyway. */ status = setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes); if(status == -1) { perror("setsockopt error: "); exit(1); } /* Bind it to the port */ status = bind(listen_fd, servinfo->ai_addr, servinfo->ai_addrlen); if(status == -1) { perror("bind error: "); exit(1); } /* Start listening to the port */ status = listen(listen_fd, BACKLOG); if(status == -1) { perror("listen error: "); exit(1); } /* Accept an incoming connection */ addr_size = sizeof(client_addr); accept_fd = accept(listen_fd, (struct sockaddr *)&client_addr, &addr_size); if(accept_fd == -1) { perror("accept error: "); exit(1); } /* Read browser request */ len = recv(accept_fd, buffer, BUFSIZE, 0); if(len == 0 || len == -1) { fprintf(stderr, "Failed to read browser request"); exit(1); } if(len > 0 && len < BUFSIZE) buffer[len] = 0; else buffer[0] = 0; /* Check HTTP method */ if(strncmp(buffer,"GET ",4) && strncmp(buffer,"get ",4)) { printf("GET method supported only.\n"); exit(1); } /* Show browser request */ fprintf(stdout, "Request:\n---\n%s\n---\n",buffer); /* buffer shuold look like 'GET URL HTTP/1.0' */ /* remove everything after URL */ for(i = 4; i < BUFSIZE; i++) { if(buffer[i] == ' ') { buffer[i] = 0; break; } } /* Check requested url matchs with filename */ if(strcmp(&buffer[5],filename)) { fprintf(stderr, "Filename not matched: %s\n",&buffer[5]); sprintf(buffer, "HTTP/1.0 404 Not Found\r\n" "Content-Type: text/html\r\n\r\n" "" "Not Found !!!" "\r\n"); send(accept_fd, buffer, strlen(buffer), 0); exit(1); } /* Write HTTP header to socket */ sprintf(buffer, "HTTP/1.0 200 OK\r\nContent-Length: %d\r\nContent-Type: application\r\n\r\n", file_size); send(accept_fd, buffer, strlen(buffer), 0); /* Send file in 8KB blocks */ while((len = read(file_fd, buffer, BUFSIZE)) > 0) send(accept_fd, buffer, len, 0); /* Cleanup */ close(listen_fd); close(accept_fd); close(file_fd); printf("Successfully sent: %s\n", file_addr); }