{"id":13549365,"url":"https://github.com/dvmatyun/web_socket","last_synced_at":"2025-09-06T15:56:47.603Z","repository":{"id":58581428,"uuid":"532495620","full_name":"dvmatyun/web_socket","owner":"dvmatyun","description":"dart / flutter webSocket package with statuses and other features","archived":false,"fork":false,"pushed_at":"2025-07-15T18:30:05.000Z","size":119,"stargazers_count":21,"open_issues_count":1,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-16T15:44:13.695Z","etag":null,"topics":["dart","flutter","flutter-package","websocket","websockets"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/websocket_universal","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dvmatyun.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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}},"created_at":"2022-09-04T09:37:52.000Z","updated_at":"2025-07-15T18:30:09.000Z","dependencies_parsed_at":"2024-03-16T21:57:58.249Z","dependency_job_id":"e5d7ea54-2136-42c6-802d-305f1eb9c4ba","html_url":"https://github.com/dvmatyun/web_socket","commit_stats":{"total_commits":42,"total_committers":4,"mean_commits":10.5,"dds":0.2857142857142857,"last_synced_commit":"6312d5d3fce2d588bed3aa92631e69d712563036"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dvmatyun/web_socket","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvmatyun%2Fweb_socket","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvmatyun%2Fweb_socket/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvmatyun%2Fweb_socket/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvmatyun%2Fweb_socket/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dvmatyun","download_url":"https://codeload.github.com/dvmatyun/web_socket/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvmatyun%2Fweb_socket/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273926536,"owners_count":25192318,"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-09-06T02:00:13.247Z","response_time":2576,"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":["dart","flutter","flutter-package","websocket","websockets"],"created_at":"2024-08-01T12:01:21.096Z","updated_at":"2025-09-06T15:56:47.543Z","avatar_url":"https://github.com/dvmatyun.png","language":"Dart","funding_links":["https://www.patreon.com/KonungzRage"],"categories":["Dart"],"sub_categories":[],"readme":"# websocket_universal\n[![CHECKOUT](https://github.com/dvmatyun/web_socket/actions/workflows/checkout.yml/badge.svg)](https://github.com/dvmatyun/web_socket/actions/workflows/checkout.yml)\n\n# Dart and Flutter webSocket client package for all the platforms (web, mobile, desktop)\n\n## Easy-to-use interface:\n1. Easy-to-use websocket methods and usage examples included!\n2. Universal socket status changes stream.\n3. Ping delay measurement and easy setup for ping/pong interaction with server!\n4. Auto-reconnection feature for `IWebSocketHandler` ws handler.\n\n## Contact \u0026 support me:\n1. [Telegram](https://t.me/DmitriiOk)\n2. [LinkedIn](https://www.linkedin.com/in/dvmatyun/)\n3. [Support me on patreon](https://www.patreon.com/KonungzRage)\n\n## Fast start:\n```dart\n// ignore_for_file: avoid_print\nimport 'package:websocket_universal/websocket_universal.dart';\n\n/// Example works with Postman Echo server\nvoid main() async {\n  /// 1. Create webSocket handler:\n  final textSocketHandler = IWebSocketHandler\u003cString, String\u003e.createClient(\n    'wss://ws.postman-echo.com/raw', // Postman echo ws server\n    SocketSimpleTextProcessor(),\n  );\n\n  /// 2. Listen to webSocket messages:\n  textSocketHandler.incomingMessagesStream.listen((inMsg) {\n    print('\u003e webSocket  got text message from server: \"$inMsg\" '\n        '[ping: ${textSocketHandler.pingDelayMs}]');\n  });\n  textSocketHandler.outgoingMessagesStream.listen((inMsg) {\n    print('\u003e webSocket sent text message to   server: \"$inMsg\" '\n        '[ping: ${textSocketHandler.pingDelayMs}]');\n  });\n\n  /// 3. Connect \u0026 send message:\n  await textSocketHandler.connect();\n  textSocketHandler.sendMessage('Hello server!');\n  await Future\u003cvoid\u003e.delayed(const Duration(seconds: 4));\n\n  // 4. Disconnect \u0026 close connection:\n  await textSocketHandler.disconnect('manual disconnect');\n  textSocketHandler.close();\n}\n```\n\n## #1 Simple example with String messages (from and to server):\nYou don't need your own ws server to run this code.  \n[Example postman echo server](https://blog.postman.com/introducing-postman-websocket-echo-service/) is used in this example.\n\n1. Send message to server using `sendMessage(Y messageToServer)` and\nlisten messages coming from server using `incomingMessagesStream`\n2. Listen to websocket states `socketStateStream` \nor all events that are happening `logEventStream`.\nDefine how you process your messages to and from server and ping/pong interaction\nusing `IMessageProcessor\u003cTin,Yout\u003e` generic interface or use convinient\n`SocketMessageProcessor` implementation (see example #2).\n\n```dart\nimport 'package:websocket_universal/websocket_universal.dart';\n\n/// Example works with Postman Echo server\nvoid main() async {\n  /// Postman echo ws server (you can use your own server URI)\n  /// 'wss://ws.postman-echo.com/raw'\n  /// For local server it could look like 'ws://127.0.0.1:42627/websocket'\n  const websocketConnectionUri = 'wss://ws.postman-echo.com/raw';\n  const textMessageToServer = 'Hello server!';\n  const connectionOptions = SocketConnectionOptions(\n    pingIntervalMs: 3000, // send Ping message every 3000 ms\n    timeoutConnectionMs: 4000, // connection fail timeout after 4000 ms\n    /// see ping/pong messages in [logEventStream] stream\n    skipPingMessages: false,\n\n    /// Set this attribute to `true` if do not need any ping/pong\n    /// messages and ping measurement. Default is `false`\n    pingRestrictionForce: false,\n  );\n\n  /// Example with simple text messages exchanges with server\n  /// (not recommended for applications)\n  /// [\u003cString, String\u003e] generic types mean that we receive [String] messages\n  /// after deserialization and send [String] messages to server.\n  final IMessageProcessor\u003cString, String\u003e textSocketProcessor =\n      SocketSimpleTextProcessor();\n  final textSocketHandler = IWebSocketHandler\u003cString, String\u003e.createClient(\n    websocketConnectionUri, // Postman echo ws server\n    textSocketProcessor,\n    connectionOptions: connectionOptions,\n  );\n\n  // Listening to webSocket status changes\n  textSocketHandler.socketHandlerStateStream.listen((stateEvent) {\n    // ignore: avoid_print\n    print('\u003e status changed to ${stateEvent.status}');\n  });\n\n  // Listening to server responses:\n  textSocketHandler.incomingMessagesStream.listen((inMsg) {\n    // ignore: avoid_print\n    print('\u003e webSocket  got text message from server: \"$inMsg\" '\n        '[ping: ${textSocketHandler.pingDelayMs}]');\n  });\n\n  // Listening to debug events inside webSocket\n  textSocketHandler.logEventStream.listen((debugEvent) {\n    // ignore: avoid_print\n    print('\u003e debug event: ${debugEvent.socketLogEventType}'\n        ' [ping=${debugEvent.pingMs} ms]. Debug message=${debugEvent.message}');\n  });\n\n  // Listening to outgoing messages:\n  textSocketHandler.outgoingMessagesStream.listen((inMsg) {\n    // ignore: avoid_print\n    print('\u003e webSocket sent text message to   server: \"$inMsg\" '\n        '[ping: ${textSocketHandler.pingDelayMs}]');\n  });\n\n  // Connecting to server:\n  final isTextSocketConnected = await textSocketHandler.connect();\n  if (!isTextSocketConnected) {\n    // ignore: avoid_print\n    print('Connection to [$websocketConnectionUri] failed for some reason!');\n    return;\n  }\n\n  textSocketHandler.sendMessage(textMessageToServer);\n\n  await Future\u003cvoid\u003e.delayed(const Duration(seconds: 30));\n  // Disconnecting from server:\n  await textSocketHandler.disconnect('manual disconnect');\n  // Disposing webSocket:\n  textSocketHandler.close();\n}\n\n```\n\n## #2 Recommended way to exchange messages with server (typed Messages):\nYou don't need your own ws server to run this code.  \n[Example postman echo server](https://blog.postman.com/introducing-postman-websocket-echo-service/) is used in this example.  \n\n```dart\nimport 'package:websocket_universal/websocket_universal.dart';\n\nvoid main() async {\n  /// Postman echo ws server (you can use your own server URI)\n  /// For local server it could look like 'ws://127.0.0.1:42627/websocket'\n  const websocketConnectionUri = 'wss://ws.postman-echo.com/raw';\n  const textMessageToServer = 'Hello server!';\n  const connectionOptions = SocketConnectionOptions(\n    pingIntervalMs: 3000, // send Ping message every 3000 ms\n    timeoutConnectionMs: 4000, // connection fail timeout after 4000 ms\n    /// see ping/pong messages in [logEventStream] stream\n    skipPingMessages: false,\n  );\n\n  /// Complex example:\n  /// Example using [ISocketMessage] and [IMessageToServer]\n  /// (recommended for applications, server must deserialize\n  /// [ISocketMessage] serialized string to [ISocketMessage] object)\n  final IMessageProcessor\u003cISocketMessage\u003cObject?\u003e, IMessageToServer\u003e\n      messageProcessor = SocketMessageProcessor();\n  final socketHandler =\n      IWebSocketHandler\u003cISocketMessage\u003cObject?\u003e, IMessageToServer\u003e.createClient(\n    websocketConnectionUri,\n    messageProcessor,\n    connectionOptions: connectionOptions,\n  );\n\n  // Listening to debug events inside webSocket\n  socketHandler.logEventStream.listen((debugEvent) {\n    // ignore: avoid_print\n    print('\u003e debug event: ${debugEvent.socketLogEventType}'\n        ' ping=${debugEvent.pingMs} ms. Debug message=${debugEvent.message}');\n  });\n\n  // Listening to webSocket status changes\n  socketHandler.socketStateStream.listen((stateEvent) {\n    // ignore: avoid_print\n    print('\u003e status changed to ${stateEvent.status}');\n  });\n\n  // [IMessageToServer] also implements [ISocketMessage] interface.\n  // So basically we are sending and receiving equally-typed messages.\n  const messageTypeStr = '[ISocketMessage]';\n  // Listening to server responses:\n  socketHandler.incomingMessagesStream.listen((inMsg) {\n    // ignore: avoid_print\n    print('\u003e webSocket  got $messageTypeStr: $inMsg');\n  });\n\n  // Listening to outgoing messages:\n  socketHandler.outgoingMessagesStream.listen((inMsg) {\n    // ignore: avoid_print\n    print('\u003e webSocket sent $messageTypeStr: $inMsg');\n  });\n\n  // Connecting to server:\n  final isConnected = await socketHandler.connect();\n\n  if (!isConnected) {\n    // ignore: avoid_print\n    print('Connection to [$websocketConnectionUri] failed for some reason!');\n    return;\n  }\n\n  // Sending message with routing path 'test' and simple JSON payload:\n  final outMsg = MessageToServerImpl.onlyHost(\n    host: 'test',\n    data: '{\"payload\": \"$textMessageToServer\"}',\n    error: null,\n  );\n  socketHandler.sendMessage(outMsg);\n\n  await Future\u003cvoid\u003e.delayed(const Duration(seconds: 8));\n  // Disconnecting from server:\n  await socketHandler.disconnect('manual disconnect');\n  // Disposing webSocket:\n  socketHandler.close();\n}\n```\n\n## #3 Handling byte messages (from and to server) on client side:\n\n```dart\nimport 'dart:convert';\n\nimport 'package:websocket_universal/websocket_universal.dart';\n\n/// Bytes array example:\nvoid main() async {\n  /// For getting/answering byte-array messages (`List\u003cint\u003e in dart`)\n  /// you will need your own server and handle messages as byte-arrays\n  /// on the backend side too. On client side it will look like this:\n  const websocketLocalExample = 'ws://127.0.0.1:42627/websocket';\n  const textMessageToServer = 'Hello server!';\n  const connectionOptions = SocketConnectionOptions(\n    pingIntervalMs: 3000, // send Ping message every 3000 ms\n    timeoutConnectionMs: 4000, // connection fail timeout after 4000 ms\n    /// see ping/pong messages in [logEventStream] stream\n    skipPingMessages: false,\n  );\n\n  final IMessageProcessor\u003cList\u003cint\u003e, List\u003cint\u003e\u003e bytesSocketProcessor =\n      SocketSimpleBytesProcessor();\n  final bytesSocketHandler =\n      IWebSocketHandler\u003cList\u003cint\u003e, List\u003cint\u003e\u003e.createClient(\n    websocketLocalExample, // Local ws server\n    bytesSocketProcessor,\n    connectionOptions: connectionOptions,\n  );\n\n  // Listening to debug events inside webSocket\n  bytesSocketHandler.logEventStream.listen((debugEvent) {\n    // ignore: avoid_print\n    print('\u003e debug event: ${debugEvent.socketLogEventType}'\n        ' ping=${debugEvent.pingMs} ms. Debug message=${debugEvent.message}');\n  });\n\n  // Listening to server responses:\n  bytesSocketHandler.incomingMessagesStream.listen((inMsg) {\n    // ignore: avoid_print\n    print('\u003e webSocket  got bytes message from server: \"$inMsg\"');\n  });\n\n  // Listening to outgoing messages:\n  bytesSocketHandler.outgoingMessagesStream.listen((inMsg) {\n    // ignore: avoid_print\n    print('\u003e webSocket sent bytes message to   server: \"$inMsg\"');\n  });\n\n  // Connecting to server:\n  final isBytesSocketConnected = await bytesSocketHandler.connect();\n  if (!isBytesSocketConnected) {\n    // ignore: avoid_print\n    print('Connection to [$websocketLocalExample] for bytesSocketHandler '\n        'failed for some reason!');\n    return;\n  }\n  final bytesMessage = utf8.encode(textMessageToServer);\n  //textMessageToServer\n  bytesSocketHandler.sendMessage(bytesMessage);\n\n  await Future\u003cvoid\u003e.delayed(const Duration(seconds: 7));\n  // Disconnecting from server:\n  await bytesSocketHandler.disconnect('manual disconnect');\n  // Disposing webSocket:\n  bytesSocketHandler.close();\n}\n\n```\n\n## #4 Advanced ISocketMessage handling. Composite server response example:\n\n```dart\nimport 'dart:convert';\n\nimport 'package:websocket_universal/websocket_universal.dart';\n\nvoid main() async {\n  /// Postman echo ws server (you can use your own server URI)\n  /// For local server it could look like 'ws://127.0.0.1:42627/websocket'\n  const websocketConnectionUri = 'wss://ws.postman-echo.com/raw';\n  const connectionOptions = SocketConnectionOptions(\n    pingIntervalMs: 3000, // send Ping message every 3000 ms\n    timeoutConnectionMs: 4000, // connection fail timeout after 4000 ms\n    /// see ping/pong messages in [logEventStream] stream\n    skipPingMessages: false,\n  );\n\n  /// Complex example:\n  /// Example using [ISocketMessage] and [IMessageToServer]\n  /// (recommended for applications, server must deserialize\n  /// [ISocketMessage] serialized string to [ISocketMessage] object)\n  final IMessageProcessor\u003cISocketMessage\u003cObject?\u003e, IMessageToServer\u003e\n      messageProcessor = SocketMessageProcessor();\n  final socketHandler =\n      IWebSocketHandler\u003cISocketMessage\u003cObject?\u003e, IMessageToServer\u003e.createClient(\n    websocketConnectionUri,\n    messageProcessor,\n    connectionOptions: connectionOptions,\n  );\n\n  /// Creating websocket_manager:\n  /// `ISocketManagerMiddleware` processes requests before sending and\n  /// after receiving ISocketMessage. See test implementation for details.\n  final ISocketManagerMiddleware middleware = SocketManagerMiddleware();\n  final IWebSocketRequestManager requestManager = WebSocketRequestManager(\n    middleware: middleware,\n    webSocketHandler: socketHandler,\n  );\n  final IWebSocketDataBridge dataBridge = WebSocketDataBridge(requestManager);\n\n  ///\n  // Connecting to server:\n  final isConnected = await socketHandler.connect();\n\n  if (!isConnected) {\n    // ignore: avoid_print\n    print('Connection to [$websocketConnectionUri] failed for some reason!');\n    return;\n  }\n\n  // Sending message with routing path 'test' and simple JSON payload:\n  final requestGame = MessageToServerImpl.duo(\n    host: TestDecoder.host,\n    topic1: CustomGameModel.topic1,\n    data: jsonEncode(\n      const CustomGameModel(\n        name: 'MakeWorld strategy',\n        playersAmount: 8,\n      ),\n    ),\n    error: null,\n  );\n  final socketRequest = SocketRequest(requestMessage: requestGame);\n\n  final result =\n      await dataBridge.singleRequestFull\u003cCustomGameModel\u003e(socketRequest);\n  // ignore: avoid_print\n  print('Got result: ${result.data}');\n\n  final outMsgList = MessageToServerImpl.duo(\n    host: TestDecoder.host,\n    topic1: CustomGameModel.topic1List,\n    data: jsonEncode([\n      const CustomGameModel(\n        name: 'MakeWorld strategy',\n        playersAmount: 8,\n      ),\n      const CustomGameModel(\n        name: 'New patch',\n        playersAmount: 4,\n      ),\n    ]),\n    error: null,\n  );\n  final socketRequestList = SocketRequest(requestMessage: outMsgList);\n\n  final listResult = await dataBridge\n      .singleRequestFull\u003cList\u003cCustomGameModel\u003e\u003e(socketRequestList);\n  // ignore: avoid_print\n  print('Got list result: ${listResult.data}');\n\n  // Creating composite request with 2 response topics required\n  final topicSingle = SocketTopicImpl.duo(\n    host: TestDecoder.host,\n    topic1: CustomGameModel.topic1,\n  );\n  final topicList = SocketTopicImpl.duo(\n    host: TestDecoder.host,\n    topic1: CustomGameModel.topic1List,\n  );\n  // Assemple composite request, that, in fact, requests CustomGameModel\n  // using [requestGame] to request single game and awaits to receive 2 topics\n  // from server: [topicSingle] and [topicList]\n  final compositeRequest = SocketRequest(\n    requestMessage: requestGame,\n    responseTopics: {topicSingle, topicList},\n  );\n  // Running task:\n  final compositeTask = dataBridge.compositeRequest(compositeRequest);\n  // Emulating server 2nd response (real server should response with 2\n  // messages without 2nd request)\n  dataBridge.requestData(socketRequestList);\n  final compositeResp = await compositeTask;\n\n  // In result we can get multiple results from composite response:\n  final responseOne = compositeResp.getData\u003cCustomGameModel\u003e();\n  final responseTwo = compositeResp.getData\u003cList\u003cCustomGameModel\u003e\u003e();\n\n  // ignore: avoid_print\n  print('Got composite result. Answers = ${compositeResp.dataCached.length}'\n      '[$responseOne] and [$responseTwo]');\n\n  // Disconnecting from server:\n  await socketHandler.disconnect('manual disconnect');\n  // Disposing webSocket:\n  requestManager.close();\n  socketHandler.close();\n}\n\n```\n\n[Source repository](https://github.com/dvmatyun/web_socket)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdvmatyun%2Fweb_socket","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdvmatyun%2Fweb_socket","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdvmatyun%2Fweb_socket/lists"}