{"id":17767841,"url":"https://github.com/awiddersheim/tcp-echo","last_synced_at":"2025-06-15T03:02:43.895Z","repository":{"id":73082558,"uuid":"115555972","full_name":"awiddersheim/tcp-echo","owner":"awiddersheim","description":"A toy project to mess with C, libuv, SO_REUSEPORT and CMake","archived":false,"fork":false,"pushed_at":"2022-04-03T20:06:35.000Z","size":193,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-01T14:20:53.337Z","etag":null,"topics":["c","cmake","libuv"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/awiddersheim.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-12-27T20:41:57.000Z","updated_at":"2022-02-18T00:07:06.000Z","dependencies_parsed_at":"2023-09-19T00:04:55.341Z","dependency_job_id":null,"html_url":"https://github.com/awiddersheim/tcp-echo","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/awiddersheim/tcp-echo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/awiddersheim%2Ftcp-echo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/awiddersheim%2Ftcp-echo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/awiddersheim%2Ftcp-echo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/awiddersheim%2Ftcp-echo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/awiddersheim","download_url":"https://codeload.github.com/awiddersheim/tcp-echo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/awiddersheim%2Ftcp-echo/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259914867,"owners_count":22931323,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c","cmake","libuv"],"created_at":"2024-10-26T20:51:41.126Z","updated_at":"2025-06-15T03:02:43.875Z","avatar_url":"https://github.com/awiddersheim.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# tcp-echo\n\n[![CircleCI](https://circleci.com/gh/awiddersheim/tcp-echo.svg?style=svg)](https://circleci.com/gh/awiddersheim/tcp-echo)\n\nThis started as a project to mess around with [C][c_lang],\n[pthreads][pthreads], [SO_REUSEPORT][reuseport] and [CMake][cmake]. That\nis largely still the case but have since transitioned away from pthreads\nto [libuv][libuv].  Can look through version control history to see\ninitial pthread work.\n\nThis has sort of evolved to become a nano version of [NGINX's][nginx]\n[architecture][nginx-arch] with a controller process controlling\nmultiple workers handling incoming connections which are [distributed by\nthe kernel][nginx-reuseport] using `SO_REUSEPORT`.\n\n```\n                  tcp-echo[ctrlr]\n            K| --\u003e \\_ tcp-echo[wrk1]\n      o/    E| --\u003e \\_ tcp-echo[wrk2]\nUser /| --\u003e R| --\u003e \\_ tcp-echo[wrk3]\n     / \\    N| --\u003e \\_ tcp-echo[wrk4]\n            E| --\u003e \\_ tcp-echo[wrk5]\n            L| --\u003e \\_ tcp-echo[wrk6]\n```\n\n## Table of Contents\n\n* [Quickstart](#quickstart)\n* [Building](#building)\n  * [Docker](#docker)\n  * [Manual](#manual)\n* [Developing](#developing)\n* [Testing](#testing)\n  * [Valgrind](#valgrind)\n  * [Performance](#performance)\n* [Configuring](#configuring)\n* [Communication](#communication)\n* [Contributing](#contributing)\n\n## Quickstart\n\nThe easiest way to get things running is with [Docker][docker]. These\nare the requirements necessary:\n\n* [Docker Engine][docker-engine-install]\n* [Docker Compose][docker-compose-install]\n\nOnce the requirements are installed simply run the following:\n\n```\n$ docker-compose up\n```\n\nNow send some data to the server:\n\n```\n$ docker-compose exec tcp-echo nc localhost 8090\nfoo\nfoo\nbar\nbar\n```\n\n## Building\n\n### Docker\n\nBuilding everything with Docker is easy.\n\n```\n$ docker build .\n```\n\nSeveral base images are supported. Can check the `requirements`\ndirectory to get an idea of which can be used and to add more.\n\nAlso, choosing between [GCC][gcc] and [Clang][clang] is possible.\n\n```\n$ docker build \\\n    --build-arg BASE_IMAGE=ubuntu:16.04 \\\n    --build-arg CC=/usr/bin/clang \\\n    --build-arg CXX=/usr/bin/clang++ \\\n    .\n```\n\n### Manual\n\nBuilding manually can be a bit more involved as several requirements are\nnecessary on most platforms. Depending on what platform you are working\non, check the `requirements` directory for one that matches. In there\nare all of the items necessary to begin building.\n\nIf building on Mac OSX then [Xcode][xcode] is required. From there, use\n[homebrew][homebrew] to get the rest of these items:\n\n```\n$ brew install \\\n    autoconf \\\n    automake \\\n    cmake \\\n    libtool \\\n    valgrind\n```\n\nRegardless of platform, once you have all of the necessary requirements\nand the code cloned locally, the project can be built using theses\nsteps:\n\n* Create and enter build directory\n\n```\n$ mkdir build \u0026\u0026 cd build\n```\n\n* Generate build files\n\n```\n$ cmake ..\n```\n\n* Build the binaries\n\n```\n$ make\n```\n\n## Developing\n\nDevelopment is again, best done in Docker by using a development version\nof the container which contains everything necessary.\n\n```\n$ docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d\n```\n\nOnce the development container is running the locally cloned code will\nbe mounted as a volume to `/tcp-echo` so you can hack on it using local\neditors. From there jump into the development container and build as\nnecessary.\n\n```\n$ docker-compose exec tcp-echo /bin/bash\n$ cmake /tcp-echo\n$ make\n$ ./tcp-echo\n```\n\nThe listening port `8090` is exposed locally so you can interact with\nthe server using local tools.\n\n## Testing\n\nThere are some simple tests that can be run to ensure basic\nfunctionality and no memory leaks. A testing version of the container\nneeds to built before running the tests.\n\n```\n$ docker build \\\n    --target test \\\n    --tag tcp-echo-test \\\n    --build-arg BASE_IMAGE=centos:7 \\\n    --build-arg CMAKE_OPTS=-DCMAKE_BUILD_TYPE=Debug \\\n    .\n```\n\nOnce the testing image has been built, run the test script.\n\n**NOTE**: At this time there are some problems with testing against the\nAlpine base image. Some issues mainly with [musl libc][musl-libc].\n\n```\n$ ./test.sh\n```\n\nAll of the tests are performed each commit to `main` by\n[CircleCI][circleci]. Once all tests pass in the [pipeline][pipeline], a\nnew image is published to [Docker Hub][dockerhub].\n\n### Valgrind\n\nCan invoke Valgrind to test for memory leaks and other memory access\nviolations.\n\n```\n$ valgrind \\\n    --error-exitcode=1 \\\n    --leak-check=full \\\n    --show-leak-kinds=all \\\n    --track-origins=yes \\\n    --trace-children=yes \\\n    ./tcp-echo\n```\n\n### Performance\n\nBeen using [tcpkali][tcpkali] as a way to test throughput and\nperformance.\n\n```\n$ tcpkali localhost:8090 \\\n    --duration 90 \\\n    --dump-one \\\n    --connections 500 \\\n    --connect-rate 300 \\\n    --channel-lifetime 1 \\\n    --message foo \\\n    --message-rate 2\n```\n\n## Configuring\n\nThere are command line arguments available to modify the programs\nbehavior. See `./tcp-echo --help` for more information. Plans are under\nway for modifying these using environment variables or a configuration\nfile.\n\n## Communication\n\n**TODO**\n\n## Contributing\n\n**TODO**\n\n[circleci]: https://circleci.com/\n[c_lang]: https://en.wikipedia.org/wiki/C_(programming_language)\n[clang]: http://clang.llvm.org/\n[cmake]: https://cmake.org/\n[docker]: https://www.docker.com/\n[dockerhub]: https://hub.docker.com/r/awiddersheim/tcp-echo/\n[docker-compose-install]: https://docs.docker.com/compose/install/\n[docker-engine-install]: https://docs.docker.com/engine/installation/\n[gcc]: https://gcc.gnu.org/\n[homebrew]: https://brew.sh/\n[libuv]: https://github.com/libuv/libuv\n[musl-libc]: https://www.musl-libc.org/\n[nginx]: https://www.nginx.com/\n[nginx-arch]: https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/\n[nginx-reuseport]: https://www.nginx.com/blog/socket-sharding-nginx-release-1-9-1/\n[pipeline]: https://circleci.com/gh/awiddersheim/workflows/tcp-echo/tree/main\n[pthreads]: https://en.wikipedia.org/wiki/POSIX_Threads\n[reuseport]: https://lwn.net/Articles/542629/\n[tcpkali]: https://github.com/satori-com/tcpkali\n[xcode]: https://developer.apple.com/xcode/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fawiddersheim%2Ftcp-echo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fawiddersheim%2Ftcp-echo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fawiddersheim%2Ftcp-echo/lists"}