我这里有一个非常简单的网络服务器(来自学校的作业)。问题是我的老师要我修复当前的问题:从我的服务器获取一个简单的请求。所以基本上他在我的终端上写了这个
$: ./wserver
^Z
[1]+ Stopped ./wserver
$: bg
$: nc localhost 8181
GET /
HTTP/1.0 404 Not Found
正如您所看到的,我没有得到一个简单的请求,而是来自我的服务器的错误代码。我想知道的是来自服务器的简单请求是什么?我抬头看了rfc 1945并得到了这个信息:Simple-Request =“GET”SP Request-URI CRLF
以下是我的以下代码(对不起,但我的一些printf是瑞典语,但我想你知道最新情况):
#include "funktioner.h"
#define BUFSIZE 4096
#define MAX_QUEUE 20
void start_server(struct sockaddr_in address, int *port, int *listener);
void wait_for_connection(struct sockaddr_in address, int *listener);
void handle_request(int new_socket);
//Main!
int main(int argc, char* argv[])
{
struct sockaddr_in address;
char *wsroot = NULL, wsroot_folder[32];
int port;
int daemon = 0;
char* log_file = NULL;
int listener;
int lfp, efp;
openlog ("wserver", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL0);
read_config_file(&port, wsroot_folder);
wsroot = get_full_path(wsroot_folder);
check_ws_root(wsroot);
parse_arguments(argc, argv, &port, &daemon, &log_file);
lfp = write_log(log_file, 0, NULL, NULL, NULL, 0, 0);
efp = get_content_type(NULL, NULL);
chdir(wsroot);
if(chroot(wsroot) != 0)
{
perror("chroot");
exit(1);
}
setuid(1000);
if(daemon)
{
daemonize(lfp, efp);
}
start_server(address, &port, &listener);
wait_for_connection(address, &listener);
close(listener);
return 0;
}
void start_server(struct sockaddr_in address, int *port, int *listener)
{
int opt = 1;
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(*port);
*listener = socket(AF_INET, SOCK_STREAM, 0);
setsockopt(*listener, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
bind(*listener, (struct sockaddr *) &address, sizeof(address));
listen(*listener, MAX_QUEUE);
}
void wait_for_connection(struct sockaddr_in address, int *listener)
{
int new_socket;
pid_t pid;
signal(SIGCHLD, SIG_IGN);
int addrlen = sizeof(address);
while(1)
{
new_socket = accept(*listener, (struct sockaddr*) &address, &addrlen);
if((pid = fork()) < 0)
{
close(new_socket);
}
else if(pid == 0)
{
close(*listener);
handle_request(new_socket);
exit(0);
}
else
{
close(new_socket);
}
}
}
void handle_request(int new_socket)
{
char buffer[BUFSIZE];
char *temp = malloc(BUFSIZE);
char *temp2 = malloc(BUFSIZE);
char *logger_line = NULL;
char *type = NULL;
char *uri = NULL;
char *httpv = NULL;
char *rp = NULL;
int openfile;
int bytes_sent = 0;
recv(new_socket, buffer, BUFSIZE, 0);
strcpy(temp, buffer);
type = strtok(temp, " ");
uri = resolve_path(strtok(NULL, " "));
httpv = strtok(NULL, "\r\n");
strcpy(temp2, buffer);
logger_line = strtok(temp2, "\r");
if(httpv != NULL)
{
if (strcmp(httpv, "HTTP/1.0") != 0 && strcmp(httpv, "HTTP/1.1") != 0)
{
strcpy(buffer, "HTTP/1.0 400 Bad Request\r\n");
bytes_sent = send(new_socket, buffer, strlen(buffer), 0);
write_log(NULL, new_socket, "-", "-", logger_line, 400, bytes_sent);
goto closing_down;
}
}
rp = realpath(uri, NULL);
if(rp == NULL)
{
create_ok_header(uri, buffer);
strcpy(buffer, "HTTP/1.0 404 Not Found\r\n");
//strcpy(buffer, "HTTP/1.0 200 OK\r\n");
bytes_sent = send(new_socket, buffer, strlen(buffer), 0);
write_log(NULL, new_socket, "-", "-", logger_line, 404, bytes_sent);
goto closing_down;
}
//GET requests
if(strcmp(type, "GET") == 0)
{
if((openfile = open(uri, O_RDONLY)) != -1)
{
create_ok_header(uri, buffer);
bytes_sent = send(new_socket, buffer, strlen(buffer), 0);
struct stat st;
stat(uri, &st);
if((bytes_sent += sendfile(new_socket, openfile, NULL, (int)st.st_size)) == -1)
{
strcpy(buffer,"HTTP/1.0 500 Internal Server Error\r\n");
bytes_sent = send(new_socket, buffer, strlen(buffer), 0);
write_log(NULL, new_socket, "-", "-", logger_line, 500, bytes_sent);
}
else
{
write_log(NULL, new_socket, "-", "-", logger_line, 200, bytes_sent);
}
}
else
{
strcpy(buffer, "HTTP/1.0 403 Forbidden\r\n");
bytes_sent = send(new_socket, buffer, strlen(buffer), 0);
write_log(NULL, new_socket, "-", "-", logger_line, 403, bytes_sent);
}
}
//HEAD requests
else if(strcmp(type, "HEAD") == 0)
{
if((openfile = open(uri, O_RDONLY)) != -1)
{
create_ok_header(uri, buffer);
bytes_sent = send(new_socket, buffer, strlen(buffer), 0);
write_log(NULL, new_socket, "-", "-", logger_line, 200, bytes_sent);
}
else
{
strcpy(buffer, "HTTP/1.0 403 Forbidden\r\n");
bytes_sent = send(new_socket, buffer, strlen(buffer), 0);
write_log(NULL, new_socket, "-", "-", logger_line, 403, bytes_sent);
}
}
else
{
strcpy(buffer, "HTTP/1.0 501 Not Implemented\r\n");
bytes_sent = send(new_socket, buffer, strlen(buffer), 0);
write_log(NULL, new_socket, "-", "-", logger_line, 501, bytes_sent);
}
closing_down:
free(rp);
free(temp);
free(temp2);
close(openfile);
close(new_socket);
}
我的职能:
#include "funktioner.h"
void read_config_file(int *port, char *wsroot)
{
FILE *config_file = fopen(".server-config", "r");
char *line = NULL;
size_t len = 0;
ssize_t read;
if(config_file == NULL)
{
exit(1);
}
while((read = getline(&line, &len, config_file)) != -1)
{
if(line[0] == '#')
{
continue;
}
if(strncmp(line, "port", 4) == 0)
{
sscanf(line, "%*s %d", port);
}
else if(strncmp(line, "root", 4) == 0)
{
sscanf(line, "%*s %s", wsroot);
}
}
fclose(config_file);
if(line)
{
free(line);
}
}
char *get_full_path(char *folder)
{
char *executing_directory = getenv("PWD");
return strcat(executing_directory, folder);
}
void check_ws_root(char *wsroot)
{
struct stat l_stat = {0};
if (stat(wsroot, &l_stat) == -1)
{
mkdir(wsroot, 0700);
}
}
void parse_arguments(int argc, char **argv, int *port, int *daemon, char **log_file)
{
int opt;
while((opt = getopt(argc, argv, "p:dl:")) != -1)
{
switch(opt)
{
case 'p':
*port = atoi(optarg);
break;
case 'd':
*daemon = 1;
break;
case 'l':
*log_file = malloc(32*4);
strcpy(*log_file, optarg);
break;
}
}
}
int write_log(char *file_name, int sockfd, char *ident, char *auth, char *request, int status, int bytes)
{
static FILE *file = NULL;
if(file == NULL)
{
if(file_name != NULL)
{
file = fopen(file_name, "a+");
return fileno(file);
}
}
if(sockfd == 0)
{
return;
}
struct sockaddr_in client;
int c_len = sizeof(client);
char buf[80];
time_t result;
result = time(NULL);
struct tm* brokentime = localtime(&result);
char now[32];
getpeername(sockfd, (struct sockaddr*)&client, &c_len);
inet_ntop(AF_INET, (struct sockaddr*)&client.sin_addr, buf, sizeof(buf));
strftime(now, 32, "%d/%b/%Y:%T %z", brokentime);
if(file == NULL && file_name == NULL)
{
syslog(LOG_NOTICE, "%s %s %s [%s] \"%s\" %d %d \n", buf, ident, auth, now, request, status, bytes);
}
else
{
fprintf(file, "%s %s %s [%s] \"%s\" %d %d \n", buf, ident, auth, now, request, status, bytes);
fflush(file);
}
}
void daemonize(int lfp, int efp)
{
pid_t pid;
umask(0);
if((pid = fork()) < 0)
{
exit(1);
}
else if(pid > 0)
{
exit(0);
}
setsid();
if((pid = fork()) < 0)
{
exit(1);
}
else if(pid > 0)
{
exit(0);
}
printf("Barnprocess = %d \n", getpid());
}
char *resolve_path(char *uri)
{
if(strncmp(uri, "/\0", 2) == 0)
{
return "index.html";
}
else if(strncmp(uri, "/", 1) == 0)
{
return uri + 1;
}
}
void create_ok_header(char *uri, char *buffer)
{
char content_type[32];
char *file_extension;
file_extension = get_extension(uri);
get_content_type(file_extension, content_type);
strcpy(buffer,"HTTP/1.0 200 OK\r\nContent-Type: ");
strcat(buffer, content_type);
strcat(buffer, "\r\n\r\n");
}
char *get_extension(char *path)
{
char *dot = strrchr(path, '.');
if(!dot || dot == path)
{
return "";
}
return dot + 1;
}
int get_content_type(char *extension, char *content_type)
{
static FILE *extension_file;
char *line = NULL;
size_t len = 0;
ssize_t read;
if(extension == NULL)
{
extension_file = fopen("supported.extensions", "r");
return fileno(extension_file);
}
else
{
while((read = getline(&line, &len, extension_file)) != -1)
{
if(line[0] == '#')
{
continue;
}
if(strncmp(line, extension, strlen(extension)) == 0)
{
sscanf(line, "%*s %s", content_type);
break;
}
}
rewind(extension_file);
}
free(line);
}
对不起,如果我没有评论我的代码,但我希望你能跟进并帮助我完成最后一步,我将永远感激(除了这个小错误,我的代码完美无缺)。在此先感谢,Viktor