{"id":33179915,"url":"https://vtortola.github.io/WebSocketListener/","last_synced_at":"2025-11-20T21:02:07.073Z","repository":{"id":14171649,"uuid":"16877717","full_name":"vtortola/WebSocketListener","owner":"vtortola","description":"A lightweight and scalable asynchronous WebSocket listener","archived":false,"fork":false,"pushed_at":"2018-04-17T21:42:10.000Z","size":8965,"stargazers_count":317,"open_issues_count":27,"forks_count":87,"subscribers_count":36,"default_branch":"master","last_synced_at":"2025-08-01T07:58:02.341Z","etag":null,"topics":["netstandard20","websocket","websocket-server","ws","wss"],"latest_commit_sha":null,"homepage":"http://vtortola.github.io/WebSocketListener","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/vtortola.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}},"created_at":"2014-02-16T03:48:25.000Z","updated_at":"2025-05-31T04:46:20.000Z","dependencies_parsed_at":"2022-08-28T23:12:27.926Z","dependency_job_id":null,"html_url":"https://github.com/vtortola/WebSocketListener","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/vtortola/WebSocketListener","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vtortola%2FWebSocketListener","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vtortola%2FWebSocketListener/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vtortola%2FWebSocketListener/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vtortola%2FWebSocketListener/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vtortola","download_url":"https://codeload.github.com/vtortola/WebSocketListener/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vtortola%2FWebSocketListener/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":285511776,"owners_count":27184237,"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-11-20T02:00:05.334Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","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":["netstandard20","websocket","websocket-server","ws","wss"],"created_at":"2025-11-16T03:00:37.817Z","updated_at":"2025-11-20T21:02:07.068Z","avatar_url":"https://github.com/vtortola.png","language":"C#","funding_links":[],"categories":["Tools per Language"],"sub_categories":["C\\#"],"readme":"[![Build status](https://ci.appveyor.com/api/projects/status/gp4qsv4xveqk2hb0?svg=true)](https://ci.appveyor.com/project/vtortola/websocketlistener-ccth8)\nWebSocketListener \n=================\n\n***\n### Please read\nThis project is considered completed. Reported bugs will be fixed, but there is no plans for new features.\n\n@deniszykov has continued its development, adding support for other platforms in his fork [deniszykov/WebSocketListener](https://github.com/deniszykov/WebSocketListener).\n***\n\nThe **WebSocketListener** class provides simple methods that listen for and accept incoming WebSocket connection requests asynchronously. It is a lightweight listener with an API very similar to the `System.Net.TcpListener` class. It **does not use** the Microsoft's `System.Net.WebSockets` namespace.\n\n It works with .NET Standard 2.0 since Version 3.0.0. [Version 2.2.4](//github.com/vtortola/WebSocketListener/tree/Version-2.2.4) is  .NET/Mono 4.5 compatible.\n\n**WebSocketListener** has been designed to provide WebSocket connectivity to other applications, in the same way that `System.Net.TcpListener` provides TCP connectivity. It is not a communication framework on its own and it does not provide any kind of publisher/subscriber pattern or reliable messaging beyond TCP.\n\n * It can work with both **Text or Binary** messages.\n * It supports `wss://`(secure). [More info](//github.com/vtortola/WebSocketListener/wiki/Enabling-WebSocket-Secure-(TLS)).\n * It supports **per-message deflate compression**. [More info](//github.com/vtortola/WebSocketListener/wiki/Deflate-extension). \n * It can work with **multiple WebSocket standards** simultaneously. [More info](//github.com/vtortola/WebSocketListener/wiki/Multiple-WebSocket-standard-support)\n * It is **extensible**. [More info](//github.com/vtortola/WebSocketListener/wiki/WebSocketListener-Extensions).\n * It is **asynchronous**. \n * It supports **Mono**. [More info](//github.com/vtortola/WebSocketListener/wiki/Mono-support)\n * It has the [**Ping/Pong** functionality](http://tools.ietf.org/html/rfc6455#section-5.5.2) **built-in**.\n * It can measure **connection latency**. [More info](//github.com/vtortola/WebSocketListener/wiki/Measuring-WebSockets-connection-latency)\n * It can work with **cookies and custom HTTP response statuses**. [More info](//github.com/vtortola/WebSocketListener/wiki/Hooking-into-the-HTTP-negotiation)\n * It detects and disconnects **half open connections**.\n * It allows to **send and receive messages as streams**. WebSocket messages are represented as delimited stream-like objects, that allows integration with other .NET objects like e.g. `StreamReader` and `StreamWriter`. Two different WebSocket messages, yield two different streams.\n * Messages reads and writes are streamed. Big messages are not held in memory during reads or writes.\n * It **handles partial frames transparently**. The WebSocket specification states that a single message can be sent across multiple individual frames. The message stream will allow to read all the message data, no matter if it was sent in a single or multiple frames.\n * It **handles interleaved control frames transparently**. The WebSocket specification states that control frames can appear interleaved with data frames, including between partial frames of the same message. The message stream will allow to read just the message data, it will skip the control frames.\n\nTake a look on the [performance and load  tests](//github.com/vtortola/WebSocketListener/wiki/WebSocketListener-performance-tests) on a simple 'echo' server.\n\n### Featured example\n\u003cimg src=\"https://cdn-1.wp.nginx.com/wp-content/themes/nginx-theme/assets/img/logo.png\" width=\"100\"\u003e\n\n[This echo server example](//github.com/vtortola/WebSocketListener/wiki/WebSocket---NGINX---SSL-Termination---Docker) uses [NGINX](//www.nginx.com/) to serve static files and WebSocket connections through the same port, providing [SSL termination](//en.wikipedia.org/wiki/TLS_termination_proxy) for both. It uses [Docker](//www.docker.com) and .Net Core 2.0.\n\n### Quickstart\n\n#### Install\n\n[WebSocketListener is available through NuGet](https://www.nuget.org/packages/vtortola.WebSocketListener/)\n\n```\nPM\u003e Install-Package vtortola.WebSocketListener\n```\n\n#### Set up\nSetting up a server and start listening for clients is very similar to a `TcpListener`. An listening endpoint and a WebSocket standard is the minimum needed to set up a server.\n\n```cs\nvar server = new WebSocketListener(new IPEndPoint(IPAddress.Any, 8006));\nserver.Standards.RegisterStandard(new WebSocketFactoryRfc6455());\nserver.StartAsync();\n```\n\nThe class ```vtortola.WebSockets.Rfc6455.WebSocketFactoryRfc6455``` gives support to the [RFC 6455](http://tools.ietf.org/html/rfc6455), that is the WebSocket standard used at the moment. Future standards can be added in the [same way](//github.com/vtortola/WebSocketListener/wiki/Multiple-WebSocket-standard-support).\n\nOptionally, you can also:\n * [enable TLS for secure WebSocket connections](//github.com/vtortola/WebSocketListener/wiki/Enabling-WebSocket-Secure-(TLS)).\n * [enable deflate compression for messages](//github.com/vtortola/WebSocketListener/wiki/Deflate-extension).\n * [customize memory use, subprotocols, queuing and ping behaviours](//github.com/vtortola/WebSocketListener/wiki/WebSocketListener-options).\n * [add customized extensions](//github.com/vtortola/WebSocketListener/wiki/WebSocketListener-Extensions).\n\n\n#### Accepting clients\nOnce the server has started, clients can be awaited asynchronously. When a client connects, a `WebSocket` object will be returned:\n\n```cs\nvar client = await server.AcceptWebSocketAsync(cancellationToken);\n```\n\nThe client provides means to read and write messages. With the client, as in the underlying `NetworkStream`, is possible to write and read at the same time even from different threads, but is not possible to read from two or more threads at the same time, same for writing.\n\n`AcceptWebSocketAsync` should be in a loop to continuously accept new clients, also wrapped in a `try/catch` since errors in the negotiation process will be thrown here. Take a look to the [simple host tutorial](https://github.com/vtortola/WebSocketListener/wiki/WebSocketListener-Echo-Server-Example).\n\n#### Receiving messages\nWith the client we can *await* a message as a readonly stream:\n\n```cs\nvar messageReadStream = await client.ReadMessageAsync(cancellationToken);\n```\n\nMessages are a stream-like objects, so is it possible to use regular .NET framework tools to work with them. The `WebSocketMessageReadStream.MessageType` property indicates the kind of content the message contains, so it can be used to select a different handling approach.\n\nThe returned `WebSocketMessageReadStream` object will contain information from the header, like type of message (Text or Binary) but not the message content, neither the message length, since a frame only contains the frame length rather than the total message length, therefore that information could be missleading.\n\nA text message can be read with a simple `StreamReader`.  It is worth remember that according to the WebSockets specs, it always uses UTF8 for text enconding:\n\n```cs\nif(messageReadStream.MessageType == WebSocketMessageType.Text)\n{\n   var msgContent = string.Empty;\n   using (var sr = new StreamReader(messageReadStream, Encoding.UTF8))\n        msgContent = await sr.ReadToEndAsync();\n}\n```\n\n```ReadMessageAsync``` should go in a loop, to read messages continuously. Writes and read can be performed at the same time. Take a look to the [simple host tutorial](//github.com/vtortola/WebSocketListener/wiki/WebSocketListener-Echo-Server-Example).\n\nAlso, a binary message can be read using regular .NET techniques:\n\n```cs\nif(messageReadStream.MessageType == WebSocketMessageType.Binary)\n{\n   using (var ms = new MemoryStream())\n   {\n       await messageReadStream.CopyToAsync(ms);\n   }\n}\n```\n\n#### Sending messages\nWriting messages is also easy. The `WebSocketMessageReadStream.CreateMessageWriter` method allows to create a write only  message:\n\n```cs\nusing (var messageWriterStream = client.CreateMessageWriter(WebSocketMessageType.Text))\n```\n\nOnce a message writer is created, regular .NET tools can be used to write in it:\n\n```cs\nusing (var sw = new StreamWriter(messageWriterStream, Encoding.UTF8))\n{\n   await sw.WriteAsync(\"Hello World!\");\n}\n```    \n\nAlso binary messages:\n\n```cs\nusing (var messageWriter = ws.CreateMessageWriter(WebSocketMessageType.Binary))\n   await myFileStream.CopyToAsync(messageWriter);\n```\n\n#### Example\nTake a look on the [WebSocketListener samples](//github.com/vtortola/WebSocketListener/wiki/WebSocketListener-Samples).\n\n### The MIT License (MIT)\n\nCopyright (c) 2014 vtortola\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/vtortola.github.io%2FWebSocketListener%2F","html_url":"https://awesome.ecosyste.ms/projects/vtortola.github.io%2FWebSocketListener%2F","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/vtortola.github.io%2FWebSocketListener%2F/lists"}