Rewrite in C. Simple TCP listener.
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1 +1,4 @@
|
|||||||
|
.idea/
|
||||||
build/
|
build/
|
||||||
|
cmake-build-debug/
|
||||||
|
cmake-build-release/
|
||||||
@@ -2,21 +2,19 @@ cmake_minimum_required(VERSION 3.15...4.0)
|
|||||||
|
|
||||||
project(SimpleHttpServer VERSION 1.0
|
project(SimpleHttpServer VERSION 1.0
|
||||||
DESCRIPTION "A simple HTTP server written in C++"
|
DESCRIPTION "A simple HTTP server written in C++"
|
||||||
LANGUAGES CXX)
|
LANGUAGES C)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
add_library(
|
add_library(
|
||||||
httpserverlib
|
httpserverlib
|
||||||
STATIC
|
STATIC
|
||||||
src/server.hpp
|
src/httpserver.h
|
||||||
src/server.cpp
|
src/httpserver.c
|
||||||
)
|
)
|
||||||
target_compile_features(httpserverlib PUBLIC cxx_std_23)
|
|
||||||
|
|
||||||
add_executable(
|
add_executable(
|
||||||
httpserver
|
httpserver
|
||||||
app/main.cpp
|
app/main.c
|
||||||
|
app/main.h
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(httpserver PUBLIC httpserverlib)
|
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