nicolas-arnaud
2 years ago
5 changed files with 214 additions and 0 deletions
@ -0,0 +1,23 @@ |
|||
NAME= server |
|||
SRCS= srcs/server.cpp srcs/tools.cpp |
|||
OBJS= $(SRCS:.cpp=.o) |
|||
CXX=c++ |
|||
CXXFLAGS= -Wextra -Wall -std=c++98 |
|||
|
|||
|
|||
all : $(NAME) |
|||
|
|||
$(NAME): $(OBJS) |
|||
$(CXX) $(OBJS) -o $(NAME) |
|||
|
|||
clean: |
|||
rm -rf $(OBJS) |
|||
|
|||
fclean: clean |
|||
rm -rf $(NAME) |
|||
|
|||
re: fclean all |
|||
|
|||
.PHONY: all clean fclean re |
|||
|
|||
|
@ -0,0 +1,12 @@ |
|||
|
|||
server { |
|||
listen 80; |
|||
server_name localhost; |
|||
|
|||
root datas; |
|||
location /site { |
|||
root datas/website; |
|||
index index.html; |
|||
try_files $uri /$uri =404; |
|||
} |
|||
} |
@ -0,0 +1,129 @@ |
|||
/**
|
|||
Handle multiple socket connections with select and fd_set on Linux |
|||
*/ |
|||
|
|||
#include <iostream> |
|||
|
|||
#include <fcntl.h> |
|||
#include <stdio.h> |
|||
#include <string.h> //strlen |
|||
#include <stdlib.h> |
|||
#include <errno.h> |
|||
#include <unistd.h> //close |
|||
#include <arpa/inet.h> //close |
|||
#include <sys/types.h> |
|||
#include <sys/socket.h> |
|||
#include <netinet/in.h> |
|||
#include <sys/time.h> //FD_SET, FD_ISSET, FD_ZERO macros |
|||
|
|||
#define PORT 80 |
|||
|
|||
int main(void) |
|||
{ |
|||
int opt = 1; |
|||
int master_socket, addrlen, new_socket, client_socket[30], max_clients = 30, activity, i, valread, sd; |
|||
int max_sd; |
|||
struct sockaddr_in address; |
|||
|
|||
char buffer[30000]; |
|||
|
|||
fd_set readfds; |
|||
|
|||
char _404[72] = "HTTP/1.1 200 OK\nContent-Type: text/plain\nContent-Length: 4\n\n404!"; |
|||
|
|||
for (i = 0; i < max_clients; i++) client_socket[i] = 0; |
|||
|
|||
if( (master_socket = socket(AF_INET, SOCK_STREAM, 0)) == 0) |
|||
{ |
|||
std::cout << std::strerror(errno) << std::endl; |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
|
|||
if( setsockopt(master_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0 ) |
|||
{ |
|||
std::cout << std::strerror(errno) << std::endl; |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
|
|||
address.sin_family = AF_INET; |
|||
address.sin_addr.s_addr = INADDR_ANY; |
|||
address.sin_port = htons( PORT ); |
|||
|
|||
if (bind(master_socket, (struct sockaddr *)&address, sizeof(address))<0) |
|||
{ |
|||
std::cout << std::strerror(errno) << std::endl; |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
std::cout << "Listener on port " << PORT << std::endl; |
|||
|
|||
if (listen(master_socket, 3) < 0) |
|||
{ |
|||
std::cout << std::strerror(errno) << std::endl; |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
|
|||
addrlen = sizeof(address); |
|||
std::cout << "Waiting for connections ..." << std::endl; |
|||
|
|||
while(1) |
|||
{ |
|||
FD_ZERO(&readfds); |
|||
FD_SET(master_socket, &readfds); |
|||
max_sd = master_socket; |
|||
|
|||
for ( i = 0 ; i < max_clients ; i++) |
|||
{ |
|||
sd = client_socket[i]; |
|||
if(sd > 0) FD_SET( sd, &readfds); |
|||
if(sd > max_sd) max_sd = sd; |
|||
} |
|||
|
|||
activity = select( max_sd + 1, &readfds, NULL, NULL, NULL); |
|||
|
|||
if ((activity < 0) && (errno!=EINTR)) |
|||
std::cout << std::strerror(errno) << std::endl; |
|||
|
|||
if (FD_ISSET(master_socket, &readfds)) |
|||
{ |
|||
if ((new_socket = accept(master_socket, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) |
|||
{ |
|||
std::cout << std::strerror(errno) << std::endl; |
|||
exit(EXIT_FAILURE); |
|||
} |
|||
fcntl(new_socket, F_GETNOSIGPIPE); |
|||
|
|||
std::cout << "New connection, socket fd is " << new_socket \ |
|||
<< ", ip is : " << inet_ntoa(address.sin_addr) \ |
|||
<< ", port : " << ntohs(address.sin_port) << std::endl; |
|||
|
|||
for (i = 0; i < max_clients; i++) |
|||
{ |
|||
if( client_socket[i] == 0 ) |
|||
{ |
|||
client_socket[i] = new_socket; |
|||
std::cout << "Adding to list of sockets as " << i << std::endl; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
for (i = 0; i < max_clients; i++) |
|||
{ |
|||
sd = client_socket[i]; |
|||
if (FD_ISSET( sd, &readfds)) |
|||
{ |
|||
valread = read(sd, buffer,30000); |
|||
if (valread == 0) |
|||
{ |
|||
getpeername(sd, (struct sockaddr*)&address, (socklen_t*)&addrlen); |
|||
std::cout << "Host disconnected, ip " << inet_ntoa(address.sin_addr)\ |
|||
<< ", port " << ntohs(address.sin_port) << std::endl; |
|||
close( sd ); |
|||
client_socket[i] = 0; |
|||
} |
|||
else send(sd, _404, strlen(_404), 0); |
|||
} |
|||
} |
|||
} |
|||
return (0); |
|||
} |
@ -0,0 +1,25 @@ |
|||
/* ************************************************************************** */ |
|||
/* */ |
|||
/* ::: :::::::: */ |
|||
/* server.hpp :+: :+: :+: */ |
|||
/* +:+ +:+ +:+ */ |
|||
/* By: narnaud <narnaud@student.42.fr> +#+ +:+ +#+ */ |
|||
/* +#+#+#+#+#+ +#+ */ |
|||
/* Created: 2022/11/02 11:16:17 by narnaud #+# #+# */ |
|||
/* Updated: 2022/11/02 12:24:25 by narnaud ### ########.fr */ |
|||
/* */ |
|||
/* ************************************************************************** */ |
|||
#pragma once |
|||
|
|||
#include <sys/socket.h> |
|||
#include <netinet/in.h> |
|||
#include <arpa/inet.h> |
|||
#include <unistd.h> |
|||
|
|||
#include <cerrno> |
|||
#include <cstring> |
|||
#include <fstream> |
|||
#include <iostream> |
|||
#include <string> |
|||
void *ft_memset(void *b, int c, size_t len); |
|||
|
@ -0,0 +1,25 @@ |
|||
/* ************************************************************************** */ |
|||
/* */ |
|||
/* ::: :::::::: */ |
|||
/* tools.cpp :+: :+: :+: */ |
|||
/* +:+ +:+ +:+ */ |
|||
/* By: narnaud <narnaud@student.42.fr> +#+ +:+ +#+ */ |
|||
/* +#+#+#+#+#+ +#+ */ |
|||
/* Created: 2022/11/02 11:01:55 by narnaud #+# #+# */ |
|||
/* Updated: 2022/11/02 11:14:36 by narnaud ### ########.fr */ |
|||
/* */ |
|||
/* ************************************************************************** */ |
|||
|
|||
#include <stddef.h> |
|||
|
|||
void *ft_memset(void *b, int c, size_t len) |
|||
{ |
|||
size_t i; |
|||
unsigned char * b_cpy; |
|||
|
|||
b_cpy = (unsigned char *)b; |
|||
i = 0; |
|||
while (i < len) |
|||
*(unsigned char *)(b_cpy + i++) = (unsigned char)c; |
|||
return ((void *)b); |
|||
} |
Loading…
Reference in new issue