{"id":22486290,"url":"https://github.com/cliffhall/node-multi-server-chat","last_synced_at":"2025-04-12T14:54:43.082Z","repository":{"id":148698010,"uuid":"138418490","full_name":"cliffhall/node-multi-server-chat","owner":"cliffhall","description":"A mesh topology multi-server chat example built with Node and Socket.io","archived":false,"fork":false,"pushed_at":"2018-07-08T20:57:49.000Z","size":739,"stargazers_count":29,"open_issues_count":0,"forks_count":8,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-26T09:39:57.127Z","etag":null,"topics":["beginner-friendly","chat","chat-application","es6","javascript","mesh-networks","multi-server","node","nodejs","socket","socket-io"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cliffhall.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":"2018-06-23T16:53:01.000Z","updated_at":"2024-08-08T06:57:59.000Z","dependencies_parsed_at":"2023-05-28T16:45:19.545Z","dependency_job_id":null,"html_url":"https://github.com/cliffhall/node-multi-server-chat","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/cliffhall%2Fnode-multi-server-chat","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cliffhall%2Fnode-multi-server-chat/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cliffhall%2Fnode-multi-server-chat/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cliffhall%2Fnode-multi-server-chat/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cliffhall","download_url":"https://codeload.github.com/cliffhall/node-multi-server-chat/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248586239,"owners_count":21128995,"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":["beginner-friendly","chat","chat-application","es6","javascript","mesh-networks","multi-server","node","nodejs","socket","socket-io"],"created_at":"2024-12-06T17:14:17.236Z","updated_at":"2025-04-12T14:54:43.061Z","avatar_url":"https://github.com/cliffhall.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# node-multi-server-chat\n\n## What is this?\nA robust multi-server chat example built with Node and Socket.io\n\nSimple Node-based chat server examples abound on GitHub. Single-endpoint examples \nare great for learning the basics of socket communications with Node, \nbut there's only so much traffic one server can handle. In short, it won't scale. \n\n## Mesh Topology\nWith this server, any number of instances can be launched on different IP/Port combinations\nand they will establish and maintain connections to each other.\n\nAfter a server instance connects to a peer, it sends a list of its users and the number of connections\nthat user currently has open. Subsequently, when users connect and disconnect, the server instance\nupdates all its peers about that user's connection status.\n\nBecause every server instance always knows which users are connected to each of its peers, \nno database is required, a common bottleneck with Star Topology systems.\n \nAnd since only a user's name and connection count is stored per connection, a 100k users with an average name \nlength of nine characters and one connection would take up less than 1MB of memory. Clients are charged with \naccumulating their own message histories.\n\n### Routing messages to recipients\nWhen a server instance receives a message for a user it doesn't know, it will forward that message to \nany peers known to have a connection to that user.\n\n### Keeping the sender's clients in sync\nThe sender's message must also be sent to all their connections on all servers so that their\nmessage histories will be able to reflect the complete discussion.\n\n### Updating clients with the user list\nWhenever a user connects to (or disconnects from) a server instance, all users connected to the mesh\nwill be sent a sorted, unique list of currently connected users.\n\n## Setup\n\n### Install Node and npm\n[Node](https://nodejs.org/en/download/) 7.7 or above (also installs npm)\n\n### Install Node modules\n```cd path/to/node-multi-server-chat``` (the rest of this document assumes you are at this location)\n\n```npm install```\n\n### Launching Socket Server Instances\nFor convenience, several npm scripts have been defined in ```package.json``` for launching the socket server instances.\n\n#### Inside your IDE\nIf you're running a modern IDE like Webstorm, you can just open the npm window and double-click on each ```start-server-x``` script. \nA separate integrated terminal will launch and you can monitor each instance's log output.\n\n#### From the command line\nIn each of four separate terminal windows, enter one of the following commands: \n\n```npm run start-server-1```\n\n```npm run start-server-2```\n\n```npm run start-server-3```\n\n```npm run start-server-4```\n\n### Launching the Chat Client Server\nA simple Express server has been included to serve the chat client, as well as an npm script to launch it.\n\n```npm run serve-client```\n\n## Design Assumptions\n  * A client should be able to connect to any running instance and chat with a user on any other instance as though they were connected to the same instance.\n  * The mechanism for connecting a user to a given instance is immaterial. It could be that the client chooses a random instance from a known list, or is assigned one by a load-balancer.\n  * A given user could be connected with multiple clients, and so when a message is sent to them, all the user's clients should receive the message.  \n  \n## Server Configuration\nA configuration file ```config.json``` contains entries for all instances, so they can listen on the right port and connect to their peers.\nFor simplicity's sake, server instances are configured to be launched on different ports of your local machine, \nbut instancescan run on any port / IP address combination:\n\n    {\n      \"id\": \"server-1\",\n      \"ip\": \"127.0.0.1\",\n      \"port\": 3001\n    },\n\n## Server Behavior\n### Peer connections\n\nWhen a server instance is launched, it begins listening on its assigned port and then attempts connection to its peers.\nIf a peer cannot be reached at launch time, instances will continue to retry until it becomes available.\nIf a connected peer disconnects at runtime, other instances will attempt to reconnect until it appears again. \n  \n  \n    Loading config from: config.json\n    Config loaded.\n    My id: server-1\n    Listening for connections on port:3001\n    Attempting to connect to peers...\n    Attempt connection to peer: server-2 at: http://127.0.0.1:3002\n    Attempt connection to peer: server-3 at: http://127.0.0.1:3003\n    Attempt connection to peer: server-4 at: http://127.0.0.1:3004\n    Outbound connection to peer: server-2\n    Outbound connection to peer: server-3\n    Outbound connection to peer: server-4\n\nWhen a server instance receives an update from a peer at connection time, it is a list of all users connected to\nthat peer. It then updates all its connected clients with the new aggregate user list.\n\n    Received update from peer: server-3\n    Replacing user list for peer: server-3\n    Updating clients with new user list...\n\n\nWhen a server instance receives an update from a peer about an individual user's connection status, it amends its\ninternal list of users. It then updates all its connected clients with the new aggregate user list.\n\n    Received update from peer: server-1\n    Replacing user Anna in list for peer: server-1\n    Updating clients with new user list...\n\n    Received update from peer: server-3\n    Adding user Billy to list for peer: server-3\n    Updating clients with new user list...\n\n    Received update from peer: server-2\n    Removing user Anna from list for peer: server-2\n    Updating clients with new user list...\n\n\n### Client connections\nWhen a client connects to an instance, it sends the user's name, and the server hangs onto the connection, \nassociating it with that user. Remember that a user can connect multiple times, so a collection of connections \nis kept for each user. Also, when a user connects, the server instance updates all its peers with the connection \nstatus of that user and then updates all its connected clients with the new aggregate user list.\n\n    User: Anna connected 1 time.\n    Updating peers with connection count for user: Anna...\n    Updating clients with new user list...\n    User: Anna connected 2 times.\n    Updating peers with connection count for user: Anna...\n    Updating clients with new user list...\n\n\nWhen a client sends a message to a user who is not on the same server instance they are connected to, the message is forwarded any peers known to have a connection to that user.\n\n    User: Billy connected 1 times.\n    Received IM from Billy to Anna: Hi Anna\n    Recipient Anna not on this server\n    Forwarding to peer: server-1 ...\n    Forwarding to peer: server-2 ...\n\nWhen a server instance receives a forwarded message from a peer for a user that has one or more connections, it sends the message\nto all of the user's connected clients. It does not forward a forwarded message.\n\n    Received forwarded IM from Billy to Anna: Hi Anna\n    Recipient Anna has 2 connection(s) to this server, sending...\n\n\n## Client Behavior\nThe rudimentary client has a dropdown with two predefined users (Anna and Billy), \nanother dropdown with four possible ports to connect to, and a 'Connect' button.\n\nThe following features are out of scope for this simple client, but have been added to a more sophisticated \n[React-based client](https://github.com/cliffhall/react-chat-client).\n\n  * Client-side message history. \n  * Client-side connected user list. This client simply logs the user list to the console when it is received. \n  \n\n### Unconnected client\n![Unconnected client](img/client-not-connected.png \"Unconnected client\")\n\nChoose a user and port then click 'Connect'. The recipient of your messages will be the user you didn't choose. \nLaunch another browser and log in as the other user, choosing either the same or a different port. Send messages\nback and forth. \n\n### User with multiple connections receives IM in all clients\n![User with multiple connections receives IM](img/multi-client-user-receives.png \"User with multiple connections receives IM\")\n\n### User with multiple connections sends IM, is notified in all clients so message histories can stay in sync\n![User with multiple connections sends IM](img/multi-client-user-sends.png \"User with multiple connections sends IM\")\n\n\n## Protocol\n![Client Connection Sequence](img/sequence-client-connection.png \"Client Connection Sequence\")\n\n![Client Disconnect Sequence](img/sequence-client-disconnect.png \"Client Disconnect Sequence\")\n\n![Client Sends IM Sequence](img/sequence-client-sends-im.png \"Client Sends IM Sequence\")\n\n![Server Connects to Peer Sequence](img/sequence-server-connects-to-peer.png \"Server Connects to Peer Sequence\")\n\n![Server Receives Forwarded IM Sequence](img/sequence-server-receives-forward.png \"Server Receives Forwarded IM Sequence\")\n\n \n\n\n## TODO \n\n  * Add shell that opens multiple clients in iframes for testing. (Thanks to Kyle at Oasis Digital for this suggestion)\n  \n  * Add cluster module support, so a single port will do on a machine, while guaranteeing optimal use of CPUs.\n ","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcliffhall%2Fnode-multi-server-chat","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcliffhall%2Fnode-multi-server-chat","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcliffhall%2Fnode-multi-server-chat/lists"}