{"id":33179428,"url":"https://github.com/OpenHFT/Chronicle-Network","last_synced_at":"2025-11-16T17:00:59.233Z","repository":{"id":25862315,"uuid":"29302186","full_name":"OpenHFT/Chronicle-Network","owner":"OpenHFT","description":"A High Performance Network ( TCP/IP ) Library","archived":true,"fork":false,"pushed_at":"2023-08-07T05:44:04.000Z","size":248986,"stargazers_count":249,"open_issues_count":0,"forks_count":87,"subscribers_count":38,"default_branch":"ea","last_synced_at":"2025-07-20T12:03:09.393Z","etag":null,"topics":["chronicle","chronicle-network","java","marshal","socket","tcp-ip","udp"],"latest_commit_sha":null,"homepage":"https://teamcity.chronicle.software/project/OpenHFT_ChronicleNetwork?mode=builds","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/OpenHFT.png","metadata":{"files":{"readme":"README.adoc","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}},"created_at":"2015-01-15T14:55:01.000Z","updated_at":"2025-05-25T03:29:25.000Z","dependencies_parsed_at":"2024-01-05T20:46:07.778Z","dependency_job_id":"bdd4be65-5147-4e49-a0c2-8d0c8781ee7d","html_url":"https://github.com/OpenHFT/Chronicle-Network","commit_stats":null,"previous_names":[],"tags_count":338,"template":false,"template_full_name":null,"purl":"pkg:github/OpenHFT/Chronicle-Network","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenHFT%2FChronicle-Network","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenHFT%2FChronicle-Network/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenHFT%2FChronicle-Network/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenHFT%2FChronicle-Network/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/OpenHFT","download_url":"https://codeload.github.com/OpenHFT/Chronicle-Network/tar.gz/refs/heads/ea","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenHFT%2FChronicle-Network/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":284742551,"owners_count":27056072,"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-16T02:00:05.974Z","response_time":65,"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":["chronicle","chronicle-network","java","marshal","socket","tcp-ip","udp"],"created_at":"2025-11-16T03:00:36.830Z","updated_at":"2025-11-16T17:00:59.214Z","avatar_url":"https://github.com/OpenHFT.png","language":"Java","funding_links":[],"categories":["网络编程","Network"],"sub_categories":[],"readme":"= Chronicle Network\nChronicle Software\n\nNOTE: Development of Chronicle-Network has been moved to closed-source, enterprise customers can access the closed-source repository link:https://github.com/ChronicleEnterprise/Chronicle-Network[here]\n\n:css-signature: demo\n:toc: macro\n:toclevels: 2\n:icons: font\n\nimage:https://maven-badges.herokuapp.com/maven-central/net.openhft/chronicle-network/badge.svg[caption=\"\",link=https://maven-badges.herokuapp.com/maven-central/net.openhft/chronicle-network]\nimage:https://javadoc.io/badge2/net.openhft/chronicle-network/javadoc.svg[link=\"https://www.javadoc.io/doc/net.openhft/chronicle-network/latest/index.html\"]\n//image:https://javadoc-badge.appspot.com/net.openhft/chronicle-network.svg?label=javadoc[JavaDoc, link=https://www.javadoc.io/doc/net.openhft/chronicle-network]\nimage:https://img.shields.io/github/license/OpenHFT/Chronicle-Network[GitHub]\nimage:https://img.shields.io/badge/release%20notes-subscribe-brightgreen[link=\"https://chronicle.software/release-notes/\"]\nimage:https://sonarcloud.io/api/project_badges/measure?project=OpenHFT_Chronicle-Network\u0026metric=alert_status[link=\"https://sonarcloud.io/dashboard?id=OpenHFT_Chronicle-Network\"]\n\ntoc::[]\n\n== About\n\nChronicle Network is a high performance network library.\n\n== Purpose\n\nThis library is designed to be lower latency and support higher throughput\n by employing techniques used in low latency trading systems.\n\n== Transports\n\nChronicle Network uses TCP.\n\nPlanned support for\n\n* Shared Memory\n\nUDP support can be found in Chronicle Network Enterprise (commercial product - contact sales@chronicle.software)\n\n== Example\n\n=== TCP Client/Server : Echo Example\n\nThe client sends a message to the server, the server immediately responds with the same message\nback to the client.\nThe full source code of this example can be found at:\n\n[source,java]\n----\nnet.openhft.performance.tests.network.SimpleServerAndClientTest.test\n\n----\n\nBelow are some of the key parts of this code explained, in a bit more detail.\n\n==== TCPRegistry\n\nThe `TCPRegistry` is most useful for unit tests, it allows you to either provide a true host and port, say \"localhost:8080\"\nor if you would rather let the application allocate you a free port at random, you can just provide a text reference to the port,\nsuch as, \"host.port\", you can provide any text you want. It will always be taken as a reference.\nThat is unless it's correctly formed like \"hostname:port\", then it will use the exact host and port you provide.\nThe reason we offer this functionality is quite often in unit tests you wish to start a test via loopback,\nfollowed often by another test, if the first test does not shut down correctly it can impact on the\nsecond test. Giving each test a unique port is one solution, but then managing those ports can become a problem\nin itself. So we created the `TCPRegistry` which manages those ports for you, when you come to clean up at the end\nof each test, all you have to do is call `TCPRegistry.reset()` and this will ensure that any open ports, will be closed.\n\n[source,java]\n----\n// This is the name of a reference to the host name and port,\n// allocated automatically to a free port on localhost\nfinal String desc = \"host.port\";\nTCPRegistry.createServerSocketChannelFor(desc);\n\n// We use an event loop rather than lots of threads\nEventLoop eg = EventGroup.builder().build();\neg.start();\n----\n\n==== Create and Start the Server\n\nThe server is configured with `TextWire`, so\nthe client must also be configured with `TextWire`. The port that we will use will be ( in this example ) determined\nby the `TCPRegistry`, of course in a real life production environment you may decide not to use the\n`TCPRegistry` or if you still use the `TCPRegistry` you can use a fixed host:port.\n\n[source,java]\n----\nfinal String expectedMessage = \"\u003cmy message\u003e\";\nAcceptorEventHandler eah = new AcceptorEventHandler(desc,\n    () -\u003e new WireEchoRequestHandler(WireType.TEXT), VanillaSessionDetails::new, 0, 0);\neg.addHandler(eah);\nfinal SocketChannel sc = TCPRegistry.createSocketChannel(desc);\nsc.configureBlocking(false);\n----\n\n==== Server Message Processing\n\nThe server code that processes a message:\n\nIn this simple example we receive and update a message and then immediately send back a response, however there are\nother solutions that can be implemented using Chronicle Network, such as the server\nresponding later to a client subscription.\n\n[source,java]\n----\n/**\n * This code is used to read the tid and payload from a wire message,\n * and send the same tid and message back to the client\n */\npublic class WireEchoRequestHandler extends WireTcpHandler {\n\n    public WireEchoRequestHandler(@NotNull Function\u003cBytes\u003c?\u003e, Wire\u003e bytesToWire) {\n        super(bytesToWire);\n    }\n\n    /**\n     * Simply reads the csp,tid and payload and sends back the tid and payload\n     *\n     * @param inWire  the wire from the client\n     * @param outWire the wire to be sent back to the server\n     * @param sd      details about this session\n     */\n    @Override\n    protected void process(@NotNull WireIn inWire,\n                           @NotNull WireOut outWire,\n                           @NotNull SessionDetailsProvider sd) {\n\n        inWire.readDocument(m -\u003e {\n            outWire.writeDocument(true, meta -\u003e meta.write(\"tid\")\n                    .int64(inWire.read(\"tid\").int64()));\n        }, d -\u003e {\n            outWire.writeDocument(false, data -\u003e data.write(\"payloadResponse\")\n                    .text(inWire.read(\"payload\").text()));\n        });\n    }\n}\n----\n\n==== Create and Start the Client\n\nThe client code that creates the `TcpChannelHub`:\n\nThe `TcpChannelHub` is used to send your messages to the server and then read the servers response.\nThe `TcpChannelHub` ensures that each response is marshalled back onto the appropriate client thread.\nIt does this through the use of a unique transaction ID ( we call this transaction ID the \"tid\" ),\n when the server responds to the client, its expected that the server sends back the tid as the very first field in the message.\nThe `TcpChannelHub` will look at each message and read the tid, and then marshall the message\nonto your appropriate client thread.\n\n[source,java]\n----\nTcpChannelHub tcpChannelHub = TcpChannelHub(null, eg, WireType.TEXT, \"\",\n    SocketAddressSupplier.uri(desc), false);\n----\n\nIn this example we are not implementing fail-over support, so the simple `SocketAddressSupplier.uri(desc)` is used.\n\n==== Client Message\n\nCreates the message the client sends to the server\n\n[source,java]\n----\n// The tid must be unique, its reflected back by the server, it must be at the start\n// of each message sent from the server to the client. Its use by the client to identify which\n// thread will handle this message\nfinal long tid = tcpChannelHub.nextUniqueTransaction(System.currentTimeMillis());\n\n// We will use a text wire backed by a elasticByteBuffer\nfinal Wire wire = new TextWire(Bytes.elasticByteBuffer());\n\nwire.writeDocument(true, w -\u003e w.write(\"tid\").int64(tid));\nwire.writeDocument(false, w -\u003e w.write(\"payload\").text(expectedMessage));\n----\n\n==== Write the Data to the Socket\n\nWhen you have multiple client threads it's important to lock before writing the data to the socket.\n\n[source,java]\n----\ntcpChannelHub.lock(() -\u003e tcpChannelHub.writeSocket(wire));\n----\n\n==== Read the Reply from the Server\n\nIn order that the correct reply can be sent to your thread you have to specify the tid.\n\n[source,java]\n----\nWire reply = tcpChannelHub.proxyReply(TimeUnit.SECONDS.toMillis(1), tid);\n----\n\n==== Check the Result of the Reply\n\n[source,java]\n----\n// Reads the reply and check the result\nreply.readDocument(null, data -\u003e {\n    final String text = data.read(\"payloadResponse\").text();\n    Assert.assertEquals(expectedMessage, text);\n});\n----\n\n==== Shutdown and Cleanup\n\n[source,java]\n----\neg.stop();\nTcpChannelHub.closeAllHubs();\nTCPRegistry.reset();\ntcpChannelHub.close();\n----\n\n== Server Threading Strategy\n\nBy default the Chronicle Network server uses a single thread to process all messages.\nHowever, if you wish to dedicate each client connection to its own thread,\nthen you can change the server threading strategy, to:\n\n----\n-DServerThreadingStrategy=CONCURRENT\n----\n\nsee the following enum for more details `net.openhft.chronicle.network.ServerThreadingStrategy`\n\n== Java Version\n\nThis library requires Java 8 or Java 11.\n\n== Testing\n\nThe target environment is to support TCP over 10 Gigabit Ethernet. In prototype\ntesting, this library has half the latency and supports 30% more bandwidth.\n\nA key test is that it shouldn't GC more than once (to allow for warm up) with -mx64m.\n\n== Downsides\n\nThis comes at the cost of scalability for large number of connections.\nIn this situation, this library should perform at least as well as Netty.\n\n== Comparisons\n\n=== Netty\n\nNetty has a much wider range of functionality, however it creates some\ngarbage in its operation (less than using plain NIO Selectors) and isn't\ndesigned to support busy waiting which gives up a small but significant delay.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FOpenHFT%2FChronicle-Network","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FOpenHFT%2FChronicle-Network","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FOpenHFT%2FChronicle-Network/lists"}