{"id":13500907,"url":"https://github.com/chris-piekarski/python-json-socket","last_synced_at":"2025-12-30T01:03:59.645Z","repository":{"id":142017730,"uuid":"1694511","full_name":"chris-piekarski/python-json-socket","owner":"chris-piekarski","description":"JSON messaging based socket interface with multi-threaded server and client","archived":false,"fork":false,"pushed_at":"2024-02-01T18:36:28.000Z","size":81,"stargazers_count":53,"open_issues_count":2,"forks_count":21,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-10-31T19:37:37.010Z","etag":null,"topics":["distributed-computing","distributed-systems","json","networking","python","threading"],"latest_commit_sha":null,"homepage":"","language":"Jupyter Notebook","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/chris-piekarski.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":"2011-05-03T03:20:37.000Z","updated_at":"2023-04-09T13:58:37.000Z","dependencies_parsed_at":null,"dependency_job_id":"f4ddb2dd-a73f-41bd-b274-ec36965f16b2","html_url":"https://github.com/chris-piekarski/python-json-socket","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chris-piekarski%2Fpython-json-socket","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chris-piekarski%2Fpython-json-socket/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chris-piekarski%2Fpython-json-socket/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chris-piekarski%2Fpython-json-socket/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chris-piekarski","download_url":"https://codeload.github.com/chris-piekarski/python-json-socket/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246155998,"owners_count":20732355,"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":["distributed-computing","distributed-systems","json","networking","python","threading"],"created_at":"2024-07-31T22:01:18.780Z","updated_at":"2025-12-30T01:03:59.641Z","avatar_url":"https://github.com/chris-piekarski.png","language":"Jupyter Notebook","readme":"python-json-socket (jsocket)\n============================\n\n[![CI](https://github.com/chris-piekarski/python-json-socket/actions/workflows/ci.yml/badge.svg)](https://github.com/chris-piekarski/python-json-socket/actions/workflows/ci.yml)\n![PyPI](https://img.shields.io/pypi/v/jsocket.svg)\n![Python Versions](https://img.shields.io/pypi/pyversions/jsocket.svg)\n![License](https://img.shields.io/pypi/l/jsocket.svg)\n\nSimple JSON-over-TCP sockets for Python. This library provides:\n\n- JsonClient/JsonServer: length‑prefixed JSON message framing over TCP\n- ThreadedServer: a single-connection server running in its own thread\n- ServerFactory/ServerFactoryThread: a per‑connection worker model for multiple clients\n\nIt aims to be small, predictable, and easy to integrate in tests or small services.\n\n\nInstall\n-------\n\n```\npip install jsocket\n```\n\nRequires Python 3.8+.\n\n\nQuickstart\n----------\n\nEcho server with `ThreadedServer` and a client:\n\n```python\nimport time\nimport jsocket\n\nclass Echo(jsocket.ThreadedServer):\n    def __init__(self, **kwargs):\n        super().__init__(**kwargs)\n        self.timeout = 2.0\n\n    # Return a dict to send a response back to the client\n    def _process_message(self, obj):\n        if isinstance(obj, dict) and 'echo' in obj:\n            return obj\n        return None\n\n# Bind to an ephemeral port (port=0)\nserver = Echo(address='127.0.0.1', port=0)\n_, port = server.socket.getsockname()\nserver.start()\n\nclient = jsocket.JsonClient(address='127.0.0.1', port=port)\nassert client.connect() is True\n\npayload = {\"echo\": \"hello\"}\nclient.send_obj(payload)\nassert client.read_obj() == payload\n\nclient.close()\nserver.stop()\nserver.join()\n```\n\nPer‑connection workers with `ServerFactory`:\n\n```python\nimport jsocket\n\nclass Worker(jsocket.ServerFactoryThread):\n    def __init__(self):\n        super().__init__()\n        self.timeout = 2.0\n\n    def _process_message(self, obj):\n        if isinstance(obj, dict) and 'message' in obj:\n            return {\"reply\": f\"got: {obj['message']}\"}\n\nserver = jsocket.ServerFactory(Worker, address='127.0.0.1', port=5489)\nserver.start()\n# Connect one or more clients; one Worker is spawned per connection\n```\n\n\nAPI Highlights\n--------------\n\n- JsonClient:\n  - `connect()` returns True on success\n  - `send_obj(dict)` sends a JSON object\n  - `read_obj()` blocks until a full message is received; raises `socket.timeout` or `RuntimeError(\"socket connection broken\")`\n  - `timeout` property controls socket timeouts\n\n- ThreadedServer:\n  - Subclass and implement `_process_message(self, obj) -\u003e Optional[dict]`\n  - Return a dict to send a response; return `None` to send nothing\n  - `start()`, `stop()`, `join()` manage the server thread\n  - `send_obj(dict)` sends to the currently connected client\n\n- ServerFactory / ServerFactoryThread:\n  - `ServerFactoryThread` is a worker that handles one client connection\n  - `ServerFactory` accepts connections and spawns a worker per client\n\n\nExamples and Tests\n------------------\n\n- Examples: see `examples/example_servers.py` and `scripts/smoke_test.py`\n- Pytest: end-to-end and listener tests under `tests/`\n  - Run: `pytest -q`\n\n\nBehavior-Driven Tests (Behave)\n------------------------------\n\n- Steps live under `features/steps/` and environment hooks in `features/environment.py`.\n- To run Behave scenarios, add one or more `.feature` files under `features/` and run:\n  - `pip install -r requirements-dev.txt`\n  - `PYTHONPATH=. behave -f progress2`\n- A minimal example feature:\n\n  ```gherkin\n  Feature: Echo round-trip\n    Scenario: client/server echo\n      Given I start the server\n      And I connect the client\n      When the client sends the object {\"echo\": \"hi\"}\n      Then the client sees a message {\"echo\": \"hi\"}\n  ```\n\n\nNotes\n-----\n\n- Message framing uses a 4‑byte big‑endian length header followed by a JSON payload encoded as UTF‑8.\n- On disconnect, reads raise `RuntimeError(\"socket connection broken\")` so callers can distinguish cleanly from timeouts.\n- Binding with `port=0` lets the OS choose an ephemeral port; find it with `server.socket.getsockname()`.\n\n\nLinks\n-----\n\n- PyPI: https://pypi.org/project/jsocket/\n- License: see `LICENSE`\n","funding_links":[],"categories":["Python"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchris-piekarski%2Fpython-json-socket","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchris-piekarski%2Fpython-json-socket","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchris-piekarski%2Fpython-json-socket/lists"}