Rewrite in C. Simple TCP listener.
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1 +1,4 @@
|
||||
.idea/
|
||||
build/
|
||||
cmake-build-debug/
|
||||
cmake-build-release/
|
||||
@@ -2,21 +2,19 @@ cmake_minimum_required(VERSION 3.15...4.0)
|
||||
|
||||
project(SimpleHttpServer VERSION 1.0
|
||||
DESCRIPTION "A simple HTTP server written in C++"
|
||||
LANGUAGES CXX)
|
||||
|
||||
|
||||
LANGUAGES C)
|
||||
|
||||
add_library(
|
||||
httpserverlib
|
||||
STATIC
|
||||
src/server.hpp
|
||||
src/server.cpp
|
||||
src/httpserver.h
|
||||
src/httpserver.c
|
||||
)
|
||||
target_compile_features(httpserverlib PUBLIC cxx_std_23)
|
||||
|
||||
add_executable(
|
||||
httpserver
|
||||
app/main.cpp
|
||||
app/main.c
|
||||
app/main.h
|
||||
)
|
||||
|
||||
target_link_libraries(httpserver PUBLIC httpserverlib)
|
||||
|
||||
20
app/main.c
Normal file
20
app/main.c
Normal file
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// Created by nazar on 12.09.2025.
|
||||
//
|
||||
|
||||
#include "main.h"
|
||||
#include <stdio.h>
|
||||
|
||||
struct HttpResponse* handleRequest(struct HttpRequest* request)
|
||||
{
|
||||
struct HttpResponse* http_response = {};
|
||||
return http_response;
|
||||
}
|
||||
|
||||
int main() {
|
||||
struct HttpServer http_server;
|
||||
printf("Starting the server...\n");
|
||||
start_http_server(&http_server, ADDRESS, PORT);
|
||||
printf("Bye!\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
#include <print>
|
||||
#include "../src/server.hpp"
|
||||
|
||||
int main() {
|
||||
SimpleHttpServer server;
|
||||
server.start_listening(8080);
|
||||
std::println("Bye!");
|
||||
}
|
||||
16
app/main.h
Normal file
16
app/main.h
Normal file
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// Created by nazar on 12.09.2025.
|
||||
//
|
||||
|
||||
#ifndef SIMPLEHTTPSERVER_MAIN_H
|
||||
#define SIMPLEHTTPSERVER_MAIN_H
|
||||
|
||||
#include "../src/httpserver.h"
|
||||
#define ADDRESS "127.0.0.1"
|
||||
#define PORT 8080
|
||||
|
||||
struct HttpResponse* handleRequest(struct HttpRequest* request);
|
||||
|
||||
int main();
|
||||
|
||||
#endif //SIMPLEHTTPSERVER_MAIN_H
|
||||
66
src/httpserver.c
Normal file
66
src/httpserver.c
Normal file
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// Created by nazar on 12.09.2025.
|
||||
//
|
||||
|
||||
#include "httpserver.h"
|
||||
#include <stdio.h>
|
||||
|
||||
void start_http_server(struct HttpServer* http_server, const char *addr, const short port)
|
||||
{
|
||||
const int server_fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (server_fd == -1)
|
||||
{
|
||||
printf("Failed to create new socket.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
struct sockaddr_in address;
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_addr.s_addr = inet_addr(addr);
|
||||
address.sin_port = htons(port);
|
||||
|
||||
const int bind_c = bind(server_fd, (struct sockaddr*)&address, sizeof(address));
|
||||
if (bind_c == -1)
|
||||
{
|
||||
printf("Failed to bind address.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
const int listen_c = listen(server_fd, 3);
|
||||
if (listen_c == -1)
|
||||
{
|
||||
printf("Failed to begin listening.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Server is listening on %s:%d...\n", addr, port);
|
||||
|
||||
size_t addr_len = sizeof(address);
|
||||
process_conn(http_server, server_fd, (struct sockaddr*)&address, (socklen_t*)&addr_len);
|
||||
|
||||
close(server_fd);
|
||||
}
|
||||
|
||||
void process_conn(struct HttpServer* http_server, const int server_fd, struct sockaddr* address, socklen_t* addr_len)
|
||||
{
|
||||
const int socket_d = accept(server_fd, address, addr_len);
|
||||
if (socket_d == -1)
|
||||
{
|
||||
printf("Failed to accept connection.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[1024] = {0};
|
||||
const ssize_t bytes_read = read(socket_d, buffer, 1024);
|
||||
printf("Client message (%ld):\n", bytes_read);
|
||||
for (int i = 0; i < bytes_read; i++)
|
||||
{
|
||||
if (buffer[i] == '\r')
|
||||
continue;
|
||||
putchar(buffer[i]);
|
||||
}
|
||||
putchar('\n');
|
||||
fflush(stdout);
|
||||
|
||||
close(socket_d);
|
||||
}
|
||||
36
src/httpserver.h
Normal file
36
src/httpserver.h
Normal file
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// Created by nazar on 12.09.2025.
|
||||
//
|
||||
// https://datatracker.ietf.org/doc/html/rfc9112#name-message
|
||||
|
||||
#ifndef SIMPLEHTTPSERVER_H
|
||||
#define SIMPLEHTTPSERVER_H
|
||||
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
struct HttpRequest
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
struct HttpResponse
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
struct HttpServer
|
||||
{
|
||||
struct HttpResponse* (*handleRequest)(struct HttpRequest* request);
|
||||
};
|
||||
|
||||
void start_http_server(struct HttpServer* http_server, const char *addr, short port);
|
||||
void process_conn(struct HttpServer* http_server, int server_fd, struct sockaddr* address, socklen_t* addr_len);
|
||||
|
||||
#endif //SIMPLEHTTPSERVER_H
|
||||
@@ -1,34 +0,0 @@
|
||||
#include "server.hpp"
|
||||
|
||||
SimpleHttpServer::SimpleHttpServer() {
|
||||
}
|
||||
|
||||
SimpleHttpServer::~SimpleHttpServer() {
|
||||
}
|
||||
|
||||
void SimpleHttpServer::start_listening(int port) {
|
||||
std::println("Starting server on port {0}...", port);
|
||||
|
||||
int serverSocket = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
sockaddr_in serverAddress;
|
||||
serverAddress.sin_family = AF_INET;
|
||||
serverAddress.sin_port = htons(port);
|
||||
serverAddress.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
bind(serverSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress));
|
||||
|
||||
listen(serverSocket, 5);
|
||||
|
||||
std::println("Listening...");
|
||||
|
||||
int clientSocket = accept(serverSocket, nullptr, nullptr);
|
||||
|
||||
char buffer[1024] = {0};
|
||||
recv(clientSocket, buffer, sizeof(buffer), 0);
|
||||
std::println("Received: {0}", buffer);
|
||||
|
||||
std::println("Closing...");
|
||||
|
||||
close(serverSocket);
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <print>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
class SimpleHttpServer {
|
||||
public:
|
||||
SimpleHttpServer();
|
||||
SimpleHttpServer(SimpleHttpServer &&) = default;
|
||||
SimpleHttpServer(const SimpleHttpServer &) = default;
|
||||
SimpleHttpServer &operator=(SimpleHttpServer &&) = default;
|
||||
SimpleHttpServer &operator=(const SimpleHttpServer &) = default;
|
||||
~SimpleHttpServer();
|
||||
|
||||
void start_listening(int port);
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user