From 8aeb18b2f1bdf06f8a94e5b49b9de21c0b3f3b28 Mon Sep 17 00:00:00 2001 From: Andy Li <1450947+andy1li@users.noreply.github.com> Date: Fri, 15 Nov 2024 16:27:37 +0800 Subject: [PATCH] Remote test for cpp --- compiled_starters/cpp/src/Server.cpp | 73 ++++++----- solutions/cpp/01-jm1/code/src/Server.cpp | 13 +- solutions/cpp/01-jm1/diff/src/Server.cpp.diff | 118 +++++------------- solutions/cpp/01-jm1/explanation.md | 35 ------ .../cpp/02-rg2/code/.codecrafters/compile.sh | 12 ++ .../cpp/02-rg2/code/.codecrafters/run.sh | 11 ++ solutions/cpp/02-rg2/code/.gitattributes | 1 + solutions/cpp/02-rg2/code/.gitignore | 49 ++++++++ solutions/cpp/02-rg2/code/CMakeLists.txt | 16 +++ solutions/cpp/02-rg2/code/README.md | 33 +++++ solutions/cpp/02-rg2/code/codecrafters.yml | 11 ++ solutions/cpp/02-rg2/code/src/Server.cpp | 61 +++++++++ .../cpp/02-rg2/code/vcpkg-configuration.json | 14 +++ solutions/cpp/02-rg2/code/vcpkg.json | 6 + solutions/cpp/02-rg2/code/your_program.sh | 25 ++++ solutions/cpp/02-rg2/diff/src/Server.cpp.diff | 69 ++++++++++ solutions/cpp/02-rg2/explanation.md | 55 ++++++++ starter_templates/cpp/code/src/Server.cpp | 73 ++++++----- 18 files changed, 470 insertions(+), 205 deletions(-) create mode 100755 solutions/cpp/02-rg2/code/.codecrafters/compile.sh create mode 100755 solutions/cpp/02-rg2/code/.codecrafters/run.sh create mode 100644 solutions/cpp/02-rg2/code/.gitattributes create mode 100644 solutions/cpp/02-rg2/code/.gitignore create mode 100644 solutions/cpp/02-rg2/code/CMakeLists.txt create mode 100644 solutions/cpp/02-rg2/code/README.md create mode 100644 solutions/cpp/02-rg2/code/codecrafters.yml create mode 100644 solutions/cpp/02-rg2/code/src/Server.cpp create mode 100644 solutions/cpp/02-rg2/code/vcpkg-configuration.json create mode 100644 solutions/cpp/02-rg2/code/vcpkg.json create mode 100755 solutions/cpp/02-rg2/code/your_program.sh create mode 100644 solutions/cpp/02-rg2/diff/src/Server.cpp.diff create mode 100644 solutions/cpp/02-rg2/explanation.md diff --git a/compiled_starters/cpp/src/Server.cpp b/compiled_starters/cpp/src/Server.cpp index 099a4c73..0fce76b9 100644 --- a/compiled_starters/cpp/src/Server.cpp +++ b/compiled_starters/cpp/src/Server.cpp @@ -12,50 +12,49 @@ int main(int argc, char **argv) { // Flush after every std::cout / std::cerr std::cout << std::unitbuf; std::cerr << std::unitbuf; + + int server_fd = socket(AF_INET, SOCK_STREAM, 0); + if (server_fd < 0) { + std::cerr << "Failed to create server socket\n"; + return 1; + } + + // Since the tester restarts your program quite often, setting SO_REUSEADDR + // ensures that we don't run into 'Address already in use' errors + int reuse = 1; + if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { + std::cerr << "setsockopt failed\n"; + return 1; + } + + struct sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(6379); + + if (bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) != 0) { + std::cerr << "Failed to bind to port 6379\n"; + return 1; + } + + int connection_backlog = 5; + if (listen(server_fd, connection_backlog) != 0) { + std::cerr << "listen failed\n"; + return 1; + } + + struct sockaddr_in client_addr; + int client_addr_len = sizeof(client_addr); + std::cout << "Waiting for a client to connect...\n"; // You can use print statements as follows for debugging, they'll be visible when running tests. std::cout << "Logs from your program will appear here!\n"; // Uncomment this block to pass the first stage - // - // int server_fd = socket(AF_INET, SOCK_STREAM, 0); - // if (server_fd < 0) { - // std::cerr << "Failed to create server socket\n"; - // return 1; - // } - // - // // Since the tester restarts your program quite often, setting SO_REUSEADDR - // // ensures that we don't run into 'Address already in use' errors - // int reuse = 1; - // if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { - // std::cerr << "setsockopt failed\n"; - // return 1; - // } - // - // struct sockaddr_in server_addr; - // server_addr.sin_family = AF_INET; - // server_addr.sin_addr.s_addr = INADDR_ANY; - // server_addr.sin_port = htons(6379); - // - // if (bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) != 0) { - // std::cerr << "Failed to bind to port 6379\n"; - // return 1; - // } - // - // int connection_backlog = 5; - // if (listen(server_fd, connection_backlog) != 0) { - // std::cerr << "listen failed\n"; - // return 1; - // } - // - // struct sockaddr_in client_addr; - // int client_addr_len = sizeof(client_addr); - // - // std::cout << "Waiting for a client to connect...\n"; - // + // // accept(server_fd, (struct sockaddr *) &client_addr, (socklen_t *) &client_addr_len); // std::cout << "Client connected\n"; - // + // // close(server_fd); return 0; diff --git a/solutions/cpp/01-jm1/code/src/Server.cpp b/solutions/cpp/01-jm1/code/src/Server.cpp index 336f97d5..73dc9398 100644 --- a/solutions/cpp/01-jm1/code/src/Server.cpp +++ b/solutions/cpp/01-jm1/code/src/Server.cpp @@ -12,13 +12,13 @@ int main(int argc, char **argv) { // Flush after every std::cout / std::cerr std::cout << std::unitbuf; std::cerr << std::unitbuf; - + int server_fd = socket(AF_INET, SOCK_STREAM, 0); if (server_fd < 0) { std::cerr << "Failed to create server socket\n"; return 1; } - + // Since the tester restarts your program quite often, setting SO_REUSEADDR // ensures that we don't run into 'Address already in use' errors int reuse = 1; @@ -26,26 +26,25 @@ int main(int argc, char **argv) { std::cerr << "setsockopt failed\n"; return 1; } - + struct sockaddr_in server_addr; server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_port = htons(6379); - + if (bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) != 0) { std::cerr << "Failed to bind to port 6379\n"; return 1; } - + int connection_backlog = 5; if (listen(server_fd, connection_backlog) != 0) { std::cerr << "listen failed\n"; return 1; } - + struct sockaddr_in client_addr; int client_addr_len = sizeof(client_addr); - std::cout << "Waiting for a client to connect...\n"; accept(server_fd, (struct sockaddr *) &client_addr, (socklen_t *) &client_addr_len); diff --git a/solutions/cpp/01-jm1/diff/src/Server.cpp.diff b/solutions/cpp/01-jm1/diff/src/Server.cpp.diff index 2236b95d..bb71a1b3 100644 --- a/solutions/cpp/01-jm1/diff/src/Server.cpp.diff +++ b/solutions/cpp/01-jm1/diff/src/Server.cpp.diff @@ -1,100 +1,40 @@ -@@ -1,62 +1,57 @@ - #include - #include - #include - #include - #include - #include - #include - #include - #include - - int main(int argc, char **argv) { - // Flush after every std::cout / std::cerr - std::cout << std::unitbuf; - std::cerr << std::unitbuf; +@@ -25,37 +25,32 @@ + if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { + std::cerr << "setsockopt failed\n"; + return 1; + } + + struct sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(6379); + + if (bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) != 0) { + std::cerr << "Failed to bind to port 6379\n"; + return 1; + } + + int connection_backlog = 5; + if (listen(server_fd, connection_backlog) != 0) { + std::cerr << "listen failed\n"; + return 1; + } + + struct sockaddr_in client_addr; + int client_addr_len = sizeof(client_addr); + std::cout << "Waiting for a client to connect...\n"; - // You can use print statements as follows for debugging, they'll be visible when running tests. - std::cout << "Logs from your program will appear here!\n"; -+ int server_fd = socket(AF_INET, SOCK_STREAM, 0); -+ if (server_fd < 0) { -+ std::cerr << "Failed to create server socket\n"; -+ return 1; -+ } ++ accept(server_fd, (struct sockaddr *) &client_addr, (socklen_t *) &client_addr_len); ++ std::cout << "Client connected\n"; - // Uncomment this block to pass the first stage -- // -- // int server_fd = socket(AF_INET, SOCK_STREAM, 0); -- // if (server_fd < 0) { -- // std::cerr << "Failed to create server socket\n"; -- // return 1; -- // } -- // -- // // Since the tester restarts your program quite often, setting SO_REUSEADDR -- // // ensures that we don't run into 'Address already in use' errors -- // int reuse = 1; -- // if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { -- // std::cerr << "setsockopt failed\n"; -- // return 1; -- // } -- // -- // struct sockaddr_in server_addr; -- // server_addr.sin_family = AF_INET; -- // server_addr.sin_addr.s_addr = INADDR_ANY; -- // server_addr.sin_port = htons(6379); -- // -- // if (bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) != 0) { -- // std::cerr << "Failed to bind to port 6379\n"; -- // return 1; -- // } -- // -- // int connection_backlog = 5; -- // if (listen(server_fd, connection_backlog) != 0) { -- // std::cerr << "listen failed\n"; -- // return 1; -- // } -- // -- // struct sockaddr_in client_addr; -- // int client_addr_len = sizeof(client_addr); -- // -- // std::cout << "Waiting for a client to connect...\n"; -- // +- // - // accept(server_fd, (struct sockaddr *) &client_addr, (socklen_t *) &client_addr_len); - // std::cout << "Client connected\n"; -- // +- // - // close(server_fd); -+ // Since the tester restarts your program quite often, setting SO_REUSEADDR -+ // ensures that we don't run into 'Address already in use' errors -+ int reuse = 1; -+ if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { -+ std::cerr << "setsockopt failed\n"; -+ return 1; -+ } -+ -+ struct sockaddr_in server_addr; -+ server_addr.sin_family = AF_INET; -+ server_addr.sin_addr.s_addr = INADDR_ANY; -+ server_addr.sin_port = htons(6379); -+ -+ if (bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) != 0) { -+ std::cerr << "Failed to bind to port 6379\n"; -+ return 1; -+ } -+ -+ int connection_backlog = 5; -+ if (listen(server_fd, connection_backlog) != 0) { -+ std::cerr << "listen failed\n"; -+ return 1; -+ } -+ -+ struct sockaddr_in client_addr; -+ int client_addr_len = sizeof(client_addr); -+ -+ std::cout << "Waiting for a client to connect...\n"; -+ -+ accept(server_fd, (struct sockaddr *) &client_addr, (socklen_t *) &client_addr_len); -+ std::cout << "Client connected\n"; -+ + close(server_fd); return 0; diff --git a/solutions/cpp/01-jm1/explanation.md b/solutions/cpp/01-jm1/explanation.md index 08233f4a..0072b775 100644 --- a/solutions/cpp/01-jm1/explanation.md +++ b/solutions/cpp/01-jm1/explanation.md @@ -5,41 +5,6 @@ Study and uncomment the relevant code: ```cpp // Uncomment this block to pass the first stage -int server_fd = socket(AF_INET, SOCK_STREAM, 0); -if (server_fd < 0) { - std::cerr << "Failed to create server socket\n"; - return 1; -} - -// Since the tester restarts your program quite often, setting SO_REUSEADDR -// ensures that we don't run into 'Address already in use' errors -int reuse = 1; -if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { - std::cerr << "setsockopt failed\n"; - return 1; -} - -struct sockaddr_in server_addr; -server_addr.sin_family = AF_INET; -server_addr.sin_addr.s_addr = INADDR_ANY; -server_addr.sin_port = htons(6379); - -if (bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) != 0) { - std::cerr << "Failed to bind to port 6379\n"; - return 1; -} - -int connection_backlog = 5; -if (listen(server_fd, connection_backlog) != 0) { - std::cerr << "listen failed\n"; - return 1; -} - -struct sockaddr_in client_addr; -int client_addr_len = sizeof(client_addr); - -std::cout << "Waiting for a client to connect...\n"; - accept(server_fd, (struct sockaddr *) &client_addr, (socklen_t *) &client_addr_len); std::cout << "Client connected\n"; diff --git a/solutions/cpp/02-rg2/code/.codecrafters/compile.sh b/solutions/cpp/02-rg2/code/.codecrafters/compile.sh new file mode 100755 index 00000000..9da226b3 --- /dev/null +++ b/solutions/cpp/02-rg2/code/.codecrafters/compile.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# +# This script is used to compile your program on CodeCrafters +# +# This runs before .codecrafters/run.sh +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit on failure + +cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake +cmake --build ./build diff --git a/solutions/cpp/02-rg2/code/.codecrafters/run.sh b/solutions/cpp/02-rg2/code/.codecrafters/run.sh new file mode 100755 index 00000000..afe22862 --- /dev/null +++ b/solutions/cpp/02-rg2/code/.codecrafters/run.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# +# This script is used to run your program on CodeCrafters +# +# This runs after .codecrafters/compile.sh +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit on failure + +exec ./build/server "$@" diff --git a/solutions/cpp/02-rg2/code/.gitattributes b/solutions/cpp/02-rg2/code/.gitattributes new file mode 100644 index 00000000..176a458f --- /dev/null +++ b/solutions/cpp/02-rg2/code/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/solutions/cpp/02-rg2/code/.gitignore b/solutions/cpp/02-rg2/code/.gitignore new file mode 100644 index 00000000..d66be1c6 --- /dev/null +++ b/solutions/cpp/02-rg2/code/.gitignore @@ -0,0 +1,49 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app +server + +# CMake +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps + +build/ +vcpkg_installed \ No newline at end of file diff --git a/solutions/cpp/02-rg2/code/CMakeLists.txt b/solutions/cpp/02-rg2/code/CMakeLists.txt new file mode 100644 index 00000000..4993f2ba --- /dev/null +++ b/solutions/cpp/02-rg2/code/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.13) + +project(redis-starter-cpp) + +file(GLOB_RECURSE SOURCE_FILES src/*.cpp) + +set(CMAKE_CXX_STANDARD 23) # Enable the C++23 standard +set(THREADS_PREFER_PTHREAD_FLAG ON) + +find_package(Threads REQUIRED) +find_package(asio CONFIG REQUIRED) + +add_executable(server ${SOURCE_FILES}) + +target_link_libraries(server PRIVATE asio asio::asio) +target_link_libraries(server PRIVATE Threads::Threads) \ No newline at end of file diff --git a/solutions/cpp/02-rg2/code/README.md b/solutions/cpp/02-rg2/code/README.md new file mode 100644 index 00000000..fb2bc917 --- /dev/null +++ b/solutions/cpp/02-rg2/code/README.md @@ -0,0 +1,33 @@ +![progress-banner](https://codecrafters.io/landing/images/default_progress_banners/redis.png) + +This is a starting point for C++ solutions to the +["Build Your Own Redis" Challenge](https://codecrafters.io/challenges/redis). + +In this challenge, you'll build a toy Redis clone that's capable of handling +basic commands like `PING`, `SET` and `GET`. Along the way we'll learn about +event loops, the Redis protocol and more. + +**Note**: If you're viewing this repo on GitHub, head over to +[codecrafters.io](https://codecrafters.io) to try the challenge. + +# Passing the first stage + +The entry point for your Redis implementation is in `src/Server.cpp`. Study and +uncomment the relevant code, and push your changes to pass the first stage: + +```sh +git commit -am "pass 1st stage" # any msg +git push origin master +``` + +That's all! + +# Stage 2 & beyond + +Note: This section is for stages 2 and beyond. + +1. Ensure you have `cmake` installed locally +1. Run `./your_program.sh` to run your Redis server, which is implemented in + `src/Server.cpp`. +1. Commit your changes and run `git push origin master` to submit your solution + to CodeCrafters. Test output will be streamed to your terminal. diff --git a/solutions/cpp/02-rg2/code/codecrafters.yml b/solutions/cpp/02-rg2/code/codecrafters.yml new file mode 100644 index 00000000..ad26fa0d --- /dev/null +++ b/solutions/cpp/02-rg2/code/codecrafters.yml @@ -0,0 +1,11 @@ +# Set this to true if you want debug logs. +# +# These can be VERY verbose, so we suggest turning them off +# unless you really need them. +debug: false + +# Use this to change the C++ version used to run your code +# on Codecrafters. +# +# Available versions: cpp-23 +language_pack: cpp-23 diff --git a/solutions/cpp/02-rg2/code/src/Server.cpp b/solutions/cpp/02-rg2/code/src/Server.cpp new file mode 100644 index 00000000..a2630c4b --- /dev/null +++ b/solutions/cpp/02-rg2/code/src/Server.cpp @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) { + // Flush after every std::cout / std::cerr + std::cout << std::unitbuf; + std::cerr << std::unitbuf; + + int server_fd = socket(AF_INET, SOCK_STREAM, 0); + if (server_fd < 0) { + std::cerr << "Failed to create server socket\n"; + return 1; + } + + // Since the tester restarts your program quite often, setting SO_REUSEADDR + // ensures that we don't run into 'Address already in use' errors + int reuse = 1; + if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { + std::cerr << "setsockopt failed\n"; + return 1; + } + + struct sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(6379); + + if (bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) != 0) { + std::cerr << "Failed to bind to port 6379\n"; + return 1; + } + + int connection_backlog = 5; + if (listen(server_fd, connection_backlog) != 0) { + std::cerr << "listen failed\n"; + return 1; + } + + struct sockaddr_in client_addr; + int client_addr_len = sizeof(client_addr); + + std::cout << "Waiting for a client to connect...\n"; + + int client_fd = accept(server_fd, (struct sockaddr *) &client_addr, (socklen_t *) &client_addr_len); + std::cout << "Client connected\n"; + + std::string response = "+PONG\r\n"; + send(client_fd, response.c_str(), response.size(), 0); + + close(client_fd); + close(server_fd); + + return 0; +} diff --git a/solutions/cpp/02-rg2/code/vcpkg-configuration.json b/solutions/cpp/02-rg2/code/vcpkg-configuration.json new file mode 100644 index 00000000..16b40d6b --- /dev/null +++ b/solutions/cpp/02-rg2/code/vcpkg-configuration.json @@ -0,0 +1,14 @@ +{ + "default-registry": { + "kind": "git", + "baseline": "c4af3593e1f1aa9e14a560a09e45ea2cb0dfd74d", + "repository": "https://github.com/microsoft/vcpkg" + }, + "registries": [ + { + "kind": "artifact", + "location": "https://github.com/microsoft/vcpkg-ce-catalog/archive/refs/heads/main.zip", + "name": "microsoft" + } + ] +} diff --git a/solutions/cpp/02-rg2/code/vcpkg.json b/solutions/cpp/02-rg2/code/vcpkg.json new file mode 100644 index 00000000..c4ec5d26 --- /dev/null +++ b/solutions/cpp/02-rg2/code/vcpkg.json @@ -0,0 +1,6 @@ +{ + "dependencies": [ + "asio", + "pthreads" + ] +} diff --git a/solutions/cpp/02-rg2/code/your_program.sh b/solutions/cpp/02-rg2/code/your_program.sh new file mode 100755 index 00000000..c493a3e7 --- /dev/null +++ b/solutions/cpp/02-rg2/code/your_program.sh @@ -0,0 +1,25 @@ +#!/bin/sh +# +# Use this script to run your program LOCALLY. +# +# Note: Changing this script WILL NOT affect how CodeCrafters runs your program. +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit early if any commands fail + +# Copied from .codecrafters/compile.sh +# +# - Edit this to change how your program compiles locally +# - Edit .codecrafters/compile.sh to change how your program compiles remotely +( + cd "$(dirname "$0")" # Ensure compile steps are run within the repository directory + cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake + cmake --build ./build +) + +# Copied from .codecrafters/run.sh +# +# - Edit this to change how your program runs locally +# - Edit .codecrafters/run.sh to change how your program runs remotely +exec ./build/server "$@" diff --git a/solutions/cpp/02-rg2/diff/src/Server.cpp.diff b/solutions/cpp/02-rg2/diff/src/Server.cpp.diff new file mode 100644 index 00000000..2b178fd5 --- /dev/null +++ b/solutions/cpp/02-rg2/diff/src/Server.cpp.diff @@ -0,0 +1,69 @@ +@@ -1,56 +1,61 @@ + #include + #include + #include + #include + #include + #include + #include + #include + #include + + int main(int argc, char **argv) { + // Flush after every std::cout / std::cerr + std::cout << std::unitbuf; + std::cerr << std::unitbuf; +- ++ + int server_fd = socket(AF_INET, SOCK_STREAM, 0); + if (server_fd < 0) { + std::cerr << "Failed to create server socket\n"; + return 1; + } +- ++ + // Since the tester restarts your program quite often, setting SO_REUSEADDR + // ensures that we don't run into 'Address already in use' errors + int reuse = 1; + if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { + std::cerr << "setsockopt failed\n"; + return 1; + } +- ++ + struct sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(6379); +- ++ + if (bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) != 0) { + std::cerr << "Failed to bind to port 6379\n"; + return 1; + } +- ++ + int connection_backlog = 5; + if (listen(server_fd, connection_backlog) != 0) { + std::cerr << "listen failed\n"; + return 1; + } +- ++ + struct sockaddr_in client_addr; + int client_addr_len = sizeof(client_addr); ++ + std::cout << "Waiting for a client to connect...\n"; + +- accept(server_fd, (struct sockaddr *) &client_addr, (socklen_t *) &client_addr_len); ++ int client_fd = accept(server_fd, (struct sockaddr *) &client_addr, (socklen_t *) &client_addr_len); + std::cout << "Client connected\n"; + ++ std::string response = "+PONG\r\n"; ++ send(client_fd, response.c_str(), response.size(), 0); ++ ++ close(client_fd); + close(server_fd); + + return 0; + } diff --git a/solutions/cpp/02-rg2/explanation.md b/solutions/cpp/02-rg2/explanation.md new file mode 100644 index 00000000..08233f4a --- /dev/null +++ b/solutions/cpp/02-rg2/explanation.md @@ -0,0 +1,55 @@ +The entry point for your Redis implementation is in `src/Server.cpp`. + +Study and uncomment the relevant code: + +```cpp +// Uncomment this block to pass the first stage + +int server_fd = socket(AF_INET, SOCK_STREAM, 0); +if (server_fd < 0) { + std::cerr << "Failed to create server socket\n"; + return 1; +} + +// Since the tester restarts your program quite often, setting SO_REUSEADDR +// ensures that we don't run into 'Address already in use' errors +int reuse = 1; +if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { + std::cerr << "setsockopt failed\n"; + return 1; +} + +struct sockaddr_in server_addr; +server_addr.sin_family = AF_INET; +server_addr.sin_addr.s_addr = INADDR_ANY; +server_addr.sin_port = htons(6379); + +if (bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) != 0) { + std::cerr << "Failed to bind to port 6379\n"; + return 1; +} + +int connection_backlog = 5; +if (listen(server_fd, connection_backlog) != 0) { + std::cerr << "listen failed\n"; + return 1; +} + +struct sockaddr_in client_addr; +int client_addr_len = sizeof(client_addr); + +std::cout << "Waiting for a client to connect...\n"; + +accept(server_fd, (struct sockaddr *) &client_addr, (socklen_t *) &client_addr_len); +std::cout << "Client connected\n"; + +close(server_fd); +``` + +Push your changes to pass the first stage: + +``` +git add . +git commit -m "pass 1st stage" # any msg +git push origin master +``` diff --git a/starter_templates/cpp/code/src/Server.cpp b/starter_templates/cpp/code/src/Server.cpp index 099a4c73..0fce76b9 100644 --- a/starter_templates/cpp/code/src/Server.cpp +++ b/starter_templates/cpp/code/src/Server.cpp @@ -12,50 +12,49 @@ int main(int argc, char **argv) { // Flush after every std::cout / std::cerr std::cout << std::unitbuf; std::cerr << std::unitbuf; + + int server_fd = socket(AF_INET, SOCK_STREAM, 0); + if (server_fd < 0) { + std::cerr << "Failed to create server socket\n"; + return 1; + } + + // Since the tester restarts your program quite often, setting SO_REUSEADDR + // ensures that we don't run into 'Address already in use' errors + int reuse = 1; + if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { + std::cerr << "setsockopt failed\n"; + return 1; + } + + struct sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(6379); + + if (bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) != 0) { + std::cerr << "Failed to bind to port 6379\n"; + return 1; + } + + int connection_backlog = 5; + if (listen(server_fd, connection_backlog) != 0) { + std::cerr << "listen failed\n"; + return 1; + } + + struct sockaddr_in client_addr; + int client_addr_len = sizeof(client_addr); + std::cout << "Waiting for a client to connect...\n"; // You can use print statements as follows for debugging, they'll be visible when running tests. std::cout << "Logs from your program will appear here!\n"; // Uncomment this block to pass the first stage - // - // int server_fd = socket(AF_INET, SOCK_STREAM, 0); - // if (server_fd < 0) { - // std::cerr << "Failed to create server socket\n"; - // return 1; - // } - // - // // Since the tester restarts your program quite often, setting SO_REUSEADDR - // // ensures that we don't run into 'Address already in use' errors - // int reuse = 1; - // if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { - // std::cerr << "setsockopt failed\n"; - // return 1; - // } - // - // struct sockaddr_in server_addr; - // server_addr.sin_family = AF_INET; - // server_addr.sin_addr.s_addr = INADDR_ANY; - // server_addr.sin_port = htons(6379); - // - // if (bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) != 0) { - // std::cerr << "Failed to bind to port 6379\n"; - // return 1; - // } - // - // int connection_backlog = 5; - // if (listen(server_fd, connection_backlog) != 0) { - // std::cerr << "listen failed\n"; - // return 1; - // } - // - // struct sockaddr_in client_addr; - // int client_addr_len = sizeof(client_addr); - // - // std::cout << "Waiting for a client to connect...\n"; - // + // // accept(server_fd, (struct sockaddr *) &client_addr, (socklen_t *) &client_addr_len); // std::cout << "Client connected\n"; - // + // // close(server_fd); return 0;