{"id":28474840,"url":"https://github.com/luismtorresv/battlesocket","last_synced_at":"2025-07-22T01:05:52.308Z","repository":{"id":296219399,"uuid":"949168350","full_name":"luismtorresv/battlesocket","owner":"luismtorresv","description":"An online, multiplayer, concurrent, client-server architecture implementation of the popular Hasbro strategy game. We designed and implemented an application-layer protocol and got ourselves accustomed to the Unix sockets interface. Project for the course «Telemática» (ST0255) taught by professor Juan Carlos Montoya Mendoza @eafit University.","archived":false,"fork":false,"pushed_at":"2025-05-29T16:44:54.000Z","size":1401,"stargazers_count":3,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-01T19:44:06.595Z","etag":null,"topics":["battleship","lab","protocol","sockets"],"latest_commit_sha":null,"homepage":"bsp://192.80.62.44:8080","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/luismtorresv.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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,"zenodo":null}},"created_at":"2025-03-15T20:39:38.000Z","updated_at":"2025-05-29T16:44:52.000Z","dependencies_parsed_at":"2025-05-29T15:44:51.049Z","dependency_job_id":"afa7df39-3a6a-4297-aaa0-50f1d8ad5e34","html_url":"https://github.com/luismtorresv/battlesocket","commit_stats":null,"previous_names":["luismtorresv/battlesocket"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/luismtorresv/battlesocket","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luismtorresv%2Fbattlesocket","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luismtorresv%2Fbattlesocket/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luismtorresv%2Fbattlesocket/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luismtorresv%2Fbattlesocket/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/luismtorresv","download_url":"https://codeload.github.com/luismtorresv/battlesocket/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luismtorresv%2Fbattlesocket/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266405405,"owners_count":23923536,"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","status":"online","status_checked_at":"2025-07-21T11:47:31.412Z","response_time":64,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["battleship","lab","protocol","sockets"],"created_at":"2025-06-07T13:35:33.707Z","updated_at":"2025-07-22T01:05:52.282Z","avatar_url":"https://github.com/luismtorresv.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!-- omit from toc --\u003e\n# battlesocket\n\u003c!-- As HTML tag to prevent it from being included in header numbering. --\u003e\n\nBattlesocket is a client-server architecture implementation of Battleship™, the\npopular Hasbro strategy game, that supports the BattleShip Protocol over TCP\nusing the Unix `sockets` application programming interface.\n\nThis README covers the features of both server and client, as well as the\nBattleShip Protocol's vocabulary and procedure.\n\n\u003c!-- omit from toc --\u003e\n## Contents\n\n- [1. Features](#1-features)\n  - [1.1. Server](#11-server)\n  - [1.2. Client](#12-client)\n- [2. Demo](#2-demo)\n- [3. Protocol](#3-protocol)\n  - [3.1. Vocabulary](#31-vocabulary)\n    - [3.1.1. Shared by client and server](#311-shared-by-client-and-server)\n    - [3.1.2. `BAD_REQUEST`](#312-bad_request)\n    - [3.1.3. Server-to-client](#313-server-to-client)\n      - [3.1.3.1. `JOINED_MATCHMAKING`](#3131-joined_matchmaking)\n      - [3.1.3.2. `START_GAME`](#3132-start_game)\n      - [3.1.3.3. `END_GAME`](#3133-end_game)\n      - [3.1.3.4. `HIT`](#3134-hit)\n      - [3.1.3.5. `MISS`](#3135-miss)\n      - [3.1.3.6. `TURN`](#3136-turn)\n    - [3.1.4. Client-to-server](#314-client-to-server)\n      - [3.1.4.1. `JOIN`](#3141-join)\n      - [3.1.4.2. `SHOT`](#3142-shot)\n      - [3.1.4.3. `SURRENDER`](#3143-surrender)\n  - [3.2. Procedure](#32-procedure)\n    - [3.2.1. Connection](#321-connection)\n    - [3.2.2. Gameplay](#322-gameplay)\n    - [3.2.3. End](#323-end)\n    - [3.2.4. Edge cases](#324-edge-cases)\n  - [3.3. Case examples](#33-case-examples)\n    - [3.3.1. Normal development of game](#331-normal-development-of-game)\n    - [3.3.2. Bad request](#332-bad-request)\n    - [3.3.3. Disconnection](#333-disconnection)\n    - [3.3.4. Surrender](#334-surrender)\n    - [3.3.5. Timeout](#335-timeout)\n    - [3.3.6. No handshake](#336-no-handshake)\n    - [3.3.7. Wrong handshake](#337-wrong-handshake)\n- [4. Compilation](#4-compilation)\n  - [4.1. Server](#41-server)\n  - [4.2. Client](#42-client)\n- [5. Conclusions](#5-conclusions)\n- [6. Authors](#6-authors)\n- [7. References](#7-references)\n- [8. License](#8-license)\n\n\n## 1. Features\n\nWhat's a protocol useful for if there are no programs that implement it?\n\n### 1.1. Server\n\nWe wrote a concurrent multi-threaded server in C, using the GNU C library for\ncommon tasks (input/output, string manipulation, etc.) as well as creation and\nhandling of POSIX threads and input/output multiplexing with `poll()`.\n\nThe server accepts incoming connections (after a handshake packet is sent).\nIt handles matchmaking in a primitive way: using a two-spots FIFO \"queue\".\n\nAfter a match starts, a thread is created to handle the game:\n\n- to keep and update its state (the boards of each player, whose turn it is)\n\n- after action messages sent by the players (which are validated by the server\n  and logged)\n\n- whose effects are notified to both players (whether it was hit or miss,\n  another player disconnected or surrendered, a change of turn, etc.) and logged\n\n- and, when it occurs, tell players who won the match.\n\nIn between the match, the server keeps a 30 seconds timer. If the player who has\nto shoot doesn't send their shot, it timeouts and the game ends (we preferred this\nover continuously switching turns if both players are idle).\n\n\n### 1.2. Client\n\nThe client's remit is:\n\n- To provide a command-line game interface to the player that tells them about:\n  - Their own board: Where their ships are and whether they have been hit\n  - Their opponent's board: Where they have shot and whether they missed or not\n  - Whose turn it is\n\n- To let the player make their shot, surrender, or find a new game.\n\n- To connect to the server using the BSP protocol through message exchanging\n  (using the Python Library `sockets` module).\n\n- To detect and notify the player if the client disconnected from the server.\n\n\n## 2. Demo\n\nServer logging on the bottom, both clients on the top.\n\n\u003e [!IMPORTANT]\n\u003e\n\u003e 👆 Click on the image below to _download_ the demo (it's a video, but GitHub\n\u003e won't show you a video player `¯\\_(ツ)_/¯`. Oh, and there's also _no_ embedded\n\u003e player🥲)\n\n[![Battlesocket demo preview.](docs/images/battlesocket-demo-preview.png)](docs/videos/battlesocket-demo.mp4)\n\n\n## 3. Protocol\n\nThe BattleShip Protocol (BSP) is an application-layer\nnetwork communication protocol for Battleship game.\nBSP relies on TCP to exchange human-readable text messages\nthat allow information sharing and event synchronization\nbetween a game server and its clients.\n\nThis section defines the semantics of BSP\nmessages, as well as the procedures regarding them.\n\n### 3.1. Vocabulary\n\nFollowing the convention suggested in the instructions handout, the BSP messages\nfollow the structure:\n\n    message = message_type data LF\n\nwhere LF acts as the message terminator.\n\nSince our game relies on a client-server architecture, some of the messages are\nspecific to either client or server, and not to its counterpart. Even though, in\ntheory, a client could send a server-specific message, the protocol procedures\nmake sure that such cases are handled correctly.\n\nWe define some common symbols that are used in the following sections:\n\n    player_letter = \"A\" | \"B\"\n\n    coordinate = row col\n    row = \"A\" | \"B\" | \"C\" | \"D\" | \"E\" | \"F\" | \"G\" | \"H\" | \"I\" | \"J\"\n    col = \"1\" | \"2\" | \"3\" | \"4\" | \"5\" | \"6\" | \"7\" | \"8\" | \"9\" | \"10\"\n\n#### 3.1.1. Shared by client and server\n\n#### 3.1.2. `BAD_REQUEST`\n\nAny malformed request (that is, one that is not a valid message of BSP), is\nreplied to with a `BAD_REQUEST` message.\n\n    bad_request = \"BAD_REQUEST\"\n\n\n#### 3.1.3. Server-to-client\n\n##### 3.1.3.1. `JOINED_MATCHMAKING`\n\nWhen a client joins a game server, we send the following message:\n\n    joined_matchmaking = \"JOINED_MATCHMAKING\"\n\n##### 3.1.3.2. `START_GAME`\n\nWhen a game room has been filled, i.e., there are two clients connected, the\nserver notifies both of them that a game will start, along with their respective\nletters (`A` or `B`) and boards:\n\n    start_game = \"START_GAME\" player_letter \"{\" (ship_type \":\" coordinate+)+ \"}\"\n    ship_type = \"carrier\" | \"battleship\" | \"cruiser\" | \"destroyer\" | \"submarine\"\n\n##### 3.1.3.3. `END_GAME`\n\nWhen a game ends the server notifies each client of the reason for ending\nthe game. These are the possible reasons to end a game:\n\n1. a player won the game\n\n2. a player disconnected from the server\n\n3. a player sent a surrender message to the server\n\n4. a player didn't send a valid action message on time and thus timed out\n\nThus we have these possible messages:\n\n    end_game = \"END_GAME\" cause player_letter\n    cause    = \"WINNER\" | \"SURRENDER\" | \"DISCONNECTION\" | \"TIMEOUT\"\n\n##### 3.1.3.4. `HIT`\n\nWhen a shot sent by the client results in a hit, the server sends this message\nto notify each client of a board update:\n\n    hit = \"HIT\" coordinate | \"HIT\" coordinate \"SUNK\"\n\n##### 3.1.3.5. `MISS`\n\nSimilarly, when a shot sent by the client does _not_ result in a hit, the server\nsends this message to notify each client of a board update:\n\n    miss = \"MISS\" coordinate\n\n##### 3.1.3.6. `TURN`\n\nWhen a player shot sent by a client is processed, it tells both players who\ngoes next through the following message:\n\n    turn = \"TURN\" player_letter\n\n#### 3.1.4. Client-to-server\n\n##### 3.1.4.1. `JOIN`\n\nA client that wants to connect to a BSP server must send a handshake message to\nverify that it's a BSP client and prevent unwanted connections:\n\n    join = \"JOIN\"\n\n##### 3.1.4.2. `SHOT`\n\nWhen a player inputs a valid coordinate, the client sends a shot message\nwith its corresponding values.\n\n    shot = \"SHOT\" coordinate\n\n##### 3.1.4.3. `SURRENDER`\n\nWhen a player gives up, the client sends the server a notification with the\nfollowing message:\n\n    surrender = \"SURRENDER\"\n\n\n### 3.2. Procedure\n\n#### 3.2.1. Connection\n\n1. A BSP client connects to a BSP server over TCP and sends the handshake\n   message (`JOIN`) within the time the server was prepared to wait (usually 2\n   seconds).\n\n      1. If the handshake message times out, the server closes the TCP\n         connection with the client.\n\n      2. After a handshake message is received, the server sends a\n         `JOINED_MATCHMAKING` message to the client, with no need for\n         acknowledgment.\n\n#### 3.2.2. Gameplay\n\n3. When there's enough players to start a game, the server sends a `START_GAME`\n   message to both connected clients with their corresponding letter and game\n   board. Each client must have a unique letter (either `A` or `B`) and they\n   should only receive their game board, not their opponent's.\n\n4. Shortly after this, the server sends a `TURN` message which notifies both\n   clients whose turn it is (either `A` or `B`).\n\n5. The current player must send a `SHOT` message within 30 seconds. Otherwise\n   the server will timeout and the server will notify the current opponent that\n   they have won the match as the current player timed out.\n\n    1. If the `SHOT` message has valid coordinates, the server notifies both\n       clients whether it was a `HIT`, and whether a ship sunk, or `MISS`.\n\n    2. Otherwise, the server sends a `BAD_REQUEST` message to the client. It's\n       not essential that the server disconnects the client if it's incorrectly\n       implemented: it will timeout eventually.\n\n #### 3.2.3. End\n\n6. After each `HIT` or `MISS`:\n\n   1. If the game end condition has been met, the server will send an `END_GAME`\n      message specifying it ends because of a `WINNER` along with the letter of\n      the player who won.\n\n   3. Otherwise, it will change the turn and notify both players by sending a\n      `TURN` message.\n\n#### 3.2.4. Edge cases\n\n7. If a client disconnection is detected, the server will notify the other\n   player who, presumably, has not disconnected, with an `END_GAME` message that\n   specifies `DISCONNECTION` and the letter of the player who disconnected.\n\n8. Similarly, if a client surrenders mid-game, the server will notify the other\n   player with an `END_GAME` message that specifies `SURRENDER` and the letter\n   of the player who surrendered.\n\n\n### 3.3. Case examples\n\nTo illustrate how the protocol, we showcase a non-exhausting collection of UML\nsequence diagrams. These include cases for:\n\n1. The \"perfect\" game, where communication between clients and server occurs\n   without issue.\n\n2. The (mostly) unproblematic game, where a few malformed requests are received,\n  amounting to no more than petty errors which can be handled.\n\n3. The fatal-error game, where it's no longer possible to keep playing and it's\n   terminated by the server.\n\n4. The handshake procedure, which verifies that the client connecting to the\n   server is a BSP client.\n\n#### 3.3.1. Normal development of game\n\n```mermaid\nsequenceDiagram\n    participant ClientA as Client A\n    participant Server as Server\n    participant ClientB as Client B\n\n    ClientA-\u003e\u003eServer: JOIN\n    Server--\u003e\u003eClientA: JOINED_MATCHMAKING\n\n    ClientB-\u003e\u003eServer: JOIN\n    Server--\u003e\u003eClientB: JOINED_MATCHMAKING\n\n    Server--\u003e\u003eClientA: START_GAME A \u003cboard\u003e\n    Server--\u003e\u003eClientB: START_GAME B \u003cboard\u003e\n\n    Server--\u003e\u003eClientA: TURN A\n    Server--\u003e\u003eClientB: TURN A\n\n    ClientA-\u003e\u003eServer: SHOT \u003ccoordinate\u003e\n\n    Server--\u003e\u003eClientA: HIT | MISS \u003ccoordinate\u003e\n    Server--\u003e\u003eClientB: HIT | MISS \u003ccoordinate\u003e\n\n    Server--\u003e\u003eClientA: TURN B\n    Server--\u003e\u003eClientB: TURN B\n\n    Note over ClientA,ClientB: ... more attempts ...\n\n    ClientA-\u003e\u003eServer: SHOT \u003ccoordinate\u003e\n    Server--\u003e\u003eClientA: HIT \u003ccoordinate\u003e SUNK\n    Server--\u003e\u003eClientB: HIT \u003ccoordinate\u003e SUNK\n\n    Server--\u003e\u003eClientA: END_GAME WINNER A\n    Server--\u003e\u003eClientB: END_GAME WINNER A\n```\n\n\n#### 3.3.2. Bad request\n\n```mermaid\nsequenceDiagram\n    participant ClientA as Client A\n    participant Server as Server\n    participant ClientB as Client B\n\n    ClientA-\u003e\u003eServer: JOIN\n    Server--\u003e\u003eClientA: JOINED_MATCHMAKING\n\n    ClientB-\u003e\u003eServer: JOIN\n    Server--\u003e\u003eClientB: JOINED_MATCHMAKING\n\n    Server--\u003e\u003eClientA: START_GAME A \u003cboard\u003e\n    Server--\u003e\u003eClientB: START_GAME B \u003cboard\u003e\n\n    Server--\u003e\u003eClientA: TURN A\n    Server--\u003e\u003eClientB: TURN A\n\nrect rgb(255,100,76)\n    ClientA-\u003e\u003eServer: SHOT K11\n    Server--\u003e\u003eClientA: BAD_REQUEST\nend\n\nrect rgb(76, 179, 255)\n    ClientA-\u003e\u003eServer: SHOOT J10\n    Server--\u003e\u003eClientA: BAD_REQUEST\nend\n\n    ClientA-\u003e\u003eServer: SHOT J10\n    Server--\u003e\u003eClientA: HIT | MISS J10\n    Server--\u003e\u003eClientB: HIT | MISS J10\n\n    Server--\u003e\u003eClientA: TURN B\n    Server--\u003e\u003eClientB: TURN B\n\n    Note over ClientA,ClientB: ... more attempts ...\n\n    ClientA-\u003e\u003eServer: SHOT \u003ccoordinate\u003e\n    Server--\u003e\u003eClientA: HIT \u003ccoordinate\u003e SUNK\n    Server--\u003e\u003eClientB: HIT \u003ccoordinate\u003e SUNK\n\n    Server--\u003e\u003eClientA: END_GAME WINNER A\n    Server--\u003e\u003eClientB: END_GAME WINNER A\n```\n\n\n#### 3.3.3. Disconnection\n\n```mermaid\nsequenceDiagram\n    participant ClientA as Client A\n    participant Server as Server\n    participant ClientB as Client B\n\n    opt Game setup and early turns\n      Note over ClientA, ClientB: Players have joined and the game has started\n    end\n\n    Server--\u003e\u003eClientA: TURN B\n    Server--\u003e\u003eClientB: TURN B\n\n    break Client B disconnected\n      Server--\u003e\u003eClientB: \"END_GAME DISCONNECTION B\"\n      Server--\u003e\u003eClientA: \"END_GAME DISCONNECTION B\"\n    end\n```\n\n\n#### 3.3.4. Surrender\n\n```mermaid\nsequenceDiagram\n    participant ClientA as Client A\n    participant Server as Server\n    participant ClientB as Client B\n\n    opt Game setup and early turns\n      Note over ClientA, ClientB: Players have joined and the game has started\n    end\n\n    Server--\u003e\u003eClientA: TURN B\n    Server--\u003e\u003eClientB: TURN B\n\n    ClientB-\u003e\u003eServer: SURRENDER\n\n    Server--\u003e\u003eClientB: \"END_GAME SURRENDER B\"\n    Server--\u003e\u003eClientA: \"END_GAME SURRENDER B\"\n```\n\n\n#### 3.3.5. Timeout\n\n```mermaid\nsequenceDiagram\n    participant ClientA as Client A\n    participant Server as Server\n    participant ClientB as Client B\n\n    opt Game setup and early turns\n      Note over ClientA, ClientB: Players have joined and the game has started\n    end\n\n    Server--\u003e\u003eClientA: TURN B\n    Server--\u003e\u003eClientB: TURN B\n\n    Note over ClientB: 30 seconds timeout (no action)\n\n    break End of the game by TIMEOUT\n      Server--\u003e\u003eClientB: \"END_GAME TIMEOUT B\"\n      Server--\u003e\u003eClientA: \"END_GAME TIMEOUT B\"\n    end\n```\n\n\n#### 3.3.6. No handshake\n\n```mermaid\nsequenceDiagram\n    participant Client as Client\n    participant Server as Server\n\n    Note over Server,Client: Client connected\n    Note over Server,Client: awaiting JOIN (5 seconds timeout)\n\n    break Handshake not received\n        Server-\u003e\u003eServer: Log handshake not received\n    end\n```\n\n\n#### 3.3.7. Wrong handshake\n\n```mermaid\nsequenceDiagram\n    participant Client as Client\n    participant Server as Server\n\n    Client-\u003e\u003eServer: PLAY\n\n    break Handshake not received\n        Server-\u003e\u003eServer: Log handshake not received\n    end\n```\n\n\n## 4. Compilation\n\n### 4.1. Server\n\nNo third-party dependencies.\n\nWe are using GNU's `gcc` compiler (specifically, version 11.4.0 on Ubuntu 22.04).\n\n```shell\n# Change working directory.\ncd battlesocket-server\n\n# Compile.\nmake -j 4\n\n# Run it with either\nmake run\n# or, to pass *optional* flags, as\n./battlesocket-server -p[port] -l[log_file]\n```\n\n\n### 4.2. Client\n\nWritten in Python 3 with an embedded third-party.\n\nTested with Python 3.11.1 on Ubuntu 22.04.\n\n```shell\n# Change your working directory to `battlesocket-client`\ncd battlesocket-client\n\n# Start Python interpreter on main module.\n# *Must* pass IP and port of host.\n# (Log path is optional, as it has a default value.)\npython src/main.py [server_ip] [server_port] -l [log_path]\n```\n\n## 5. Conclusions\n\nWe designed an application-layer network communication protocol that works well\nto handle a Battleship game. We tried to define it once and for all from the\nstart, but it took a lot of iterations and nitpicking on details to finally\nsettle on its design.\n\nDuring its development, we learned how to use the basic system calls provided by\nthe Unix `sockets` API. Besides knowing how to interact with this interface, we\nhad to dig a bit more into the way it's implemented to understand its\nlimitations and work around them one way or another.\n\nAs network applications are typically concurrent, we also learned —despite none\nof us having taken a course in operating systems— about threads and,\nconsequently, about the problem of synchronization which is usually solved\nthrough the use of mutexes or \"locks\". Trying to understand how mutexes work led\nus to learn about atomic operations in computer processors.\n\nIn spite of strong suggestion to the contrary, we decided to create a new thread\neach time a game started instead of keeping a thread pool. We saw some simple\nthread pool implementations but noticed how their higher complexity can carry\nalong additional problems. These were not worth trying to solve as we had no\nreal need to handle time-sensitive communications.\n\n## 6. Authors\n\nJerónimo Acosta Acevedo,\nJuan José Restrepo Higuita,\nand Luis Miguel Torres Villegas.\n\n## 7. References\n\n1. Hall, Brian. _Beej’s Guide to Network Programming: Using Internet Sockets_.\n   2025, https://beej.us/guide/bgnet/.\n\n   Explains how to use the system calls provided by the Unix API for `sockets`\n   in a friendly and straightforward way.\n   Section 7.2 _`poll()`—Synchronous I/O Multiplexing_ was particularly useful\n   in implementing the thread function that handled a game.\n\n2. Blelloch, Guy. _Linux Tutorial: POSIX Threads._ 15-492: Parallel Algorithms\n   (Fall 2007),\n   https://www.cs.cmu.edu/afs/cs/academic/class/15492-f07/www/pthreads.html.\n\n   Goes over the basic functions provided by the POSIX thread (`pthread`)\n   libraries.\n   It covers creation, termination, and synchronization using mutexes, among\n   other more advanced subjects.\n\n3. Parmaksız, Orhun. _battleship-rs_. 0.1.1, 14 May 2022,\n   https://github.com/orhun/battleship-rs.\n\n   Server-side Rust implementation of Battleship. That is, it provides both the\n   service _and_ the command-line text interface through a TCP connection (more\n   or less like a mainframe interacting with dumb terminals). We designed the\n   CLI for our implementation somewhat based off this one.\n\n\n\n## 8. License\n\nCopyright 2025 The Authors\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluismtorresv%2Fbattlesocket","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fluismtorresv%2Fbattlesocket","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluismtorresv%2Fbattlesocket/lists"}