diff options
author | Kyle K <kylek389@gmail.com> | 2011-09-15 02:14:13 -0500 |
---|---|---|
committer | Kamil Kaminski <kamilkss@gmail.com> | 2011-09-15 02:23:41 -0500 |
commit | 3235e6a3bc66cf7c6667a1cd3d1485431e50197c (patch) | |
tree | 97221e5cd03a3a45bf03de2e55a2a79da9f033e6 | |
parent | 76765068743a956fb68d9b942426bcd43e84f092 (diff) | |
download | sandbox-3235e6a3bc66cf7c6667a1cd3d1485431e50197c.tar.gz sandbox-3235e6a3bc66cf7c6667a1cd3d1485431e50197c.tar.bz2 sandbox-3235e6a3bc66cf7c6667a1cd3d1485431e50197c.zip |
tcpserver2: import
-rw-r--r-- | tcpserver2.c | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/tcpserver2.c b/tcpserver2.c new file mode 100644 index 0000000..629feef --- /dev/null +++ b/tcpserver2.c @@ -0,0 +1,164 @@ +/* Kamil Kaminski + * kkamin8@uic.edu + * + * + * Note: implement content-size, if index.html is not present, generate a page + * that lists root directory, you can use select() to deal with multiple + * requests instead of forking + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <sys/uio.h> +#include <sys/socket.h> +#include <sys/select.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <sys/wait.h> + +int main(int argc, char **argv) +{ + if (argc != 3) + { + fprintf(stderr, "usage: %s <port> <dir>\n", argv[0]); + exit(1); + } + + int server_sockfd, ret; + + if ((server_sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) + { + perror("socket"); + close(server_sockfd); + exit(-1); + } + + /* allow fast reuse of ports */ + int reuse_true = 1; + setsockopt(server_sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse_true, + sizeof(reuse_true)); + + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(atoi(argv[1])); + addr.sin_addr.s_addr = INADDR_ANY; + + if (bind(server_sockfd, (struct sockaddr *) &addr, sizeof(addr)) == -1) + { + perror("bind"); + exit(-1); + } + + if (listen(server_sockfd, 0) == -1) + { + perror("listen"); + exit(-1); + } + + while (1) + { + int sockfd; + struct sockaddr_in remote_addr; + unsigned int socklen = sizeof(remote_addr); + sockfd = accept(server_sockfd, (struct sockaddr *) &remote_addr, &socklen); + if (sockfd == -1) + { + perror("accept"); + continue; + } + + char ipstr[INET6_ADDRSTRLEN]; + inet_ntop(remote_addr.sin_family, &remote_addr.sin_addr, ipstr, sizeof(ipstr)); + printf("got connection from %s\n", ipstr); + + /* read the http header request from the client */ + char recv_buff[512] = { 0 }; + if ((ret = recv(sockfd, recv_buff, sizeof(recv_buff), 0)) < 0) + { + perror("recv"); + shutdown(sockfd, SHUT_RDWR); + close(sockfd); + continue; + } + /* printf("%s", recv_buff); */ + + char *p; + if (!(p = strstr(recv_buff, "GET"))) + continue; + + char filereq[100] = { 0 }; + sscanf(p, "GET %s HTTP/1.*[01]\r\n", filereq); + printf("requested file: \"%s\"\n", filereq); + + char path[200] = { 0 }; + sprintf(path, "%s%s", argv[2], filereq[strlen(filereq) - 1] == '/' ? + "/index.html" : filereq); + printf("path is: \"%s\"\n", path); + + struct stat stat_buff; + if (stat(path, &stat_buff) == -1) + { + perror("stat"); + char err[] = "HTTP/1.0 404 Not Found\r\n\r\n"; + send(sockfd, err, sizeof(err), 0); + } + else + { + pid_t pid; + if ((pid = fork()) == 0) + { + char http_header[100] = { 0 }; + char *p = strstr(path, "."), *type = NULL; + if (p) + { + if (strcmp(p, ".html") == 0) + type = "Content-Type: text/html\r\n"; + else if (strcmp(p, ".gif") == 0) + type = "Content-Type: image/gif\r\n"; + else if (strcmp(p, ".png") == 0) + type = "Content-Type: image/png\r\n"; + else if (strcmp(p, ".jpeg") == 0 || strcmp(p, ".jpg") == 0) + type = "Content-Type: image/jpeg\r\n"; + else if (strcmp(p, ".pdf") == 0) + type = "Content-Type: application/pdf\r\n"; + } + sprintf(http_header, "%s%s\r\n", "HTTP/1.1 200 OK\r\n", type ? type : "\r\n"); + /* printf("http header:\n\"%s\"\n", http_header); */ + + FILE *fp = fopen(path, "r"); + char *file = (char *) malloc(sizeof(char) * (stat_buff.st_size + strlen(http_header))); + if (file && fp) + { + memcpy(file, http_header, strlen(http_header)); + fread(file + strlen(http_header), stat_buff.st_size, sizeof(char), fp); + send(sockfd, file, stat_buff.st_size + strlen(http_header), 0); + free(file); + } + fclose(fp); + shutdown(sockfd, SHUT_RDWR); + close(sockfd); + exit(0); + } + else if (pid > 0) + { + wait(NULL); + } + else + { + perror("fork"); + shutdown(sockfd, SHUT_RDWR); + close(sockfd); + } + } + } + + shutdown(server_sockfd, SHUT_RDWR); + close(server_sockfd); +} + |