examples/echo.rs
A TCP echo server on every core.
cargo run --release --example echo
nc 127.0.0.1 7000docs
Requirements, a first server, and where everything else is documented. The API reference for each crate is on docs.rs.
The crates are on crates.io. Add the runtime and the layers you need; giong-http
takes --features tls for HTTPS and --features client for its client.
cargo add giong
cargo add giong-http # or giong-web for routing, middleware and JSON
Put this in src/main.rs. Every worker binds its own SO_REUSEPORT
listener on the same port, and the kernel spreads connections across cores.
use std::time::Duration;
use giong::net::TcpListener;
use giong_http::{Request, Response, Server};
async fn handler(req: Request) -> Response {
match (req.method(), req.path()) {
("GET", "/health") => Response::text("ok"),
("POST", "/echo") => Response::new(200).body(req.body().to_vec()),
_ => Response::new(404),
}
}
fn main() -> std::io::Result<()> {
giong::Builder::new()
.shutdown_on_signals(true) // Ctrl-C / SIGTERM stop it gracefully
.shutdown_grace(Duration::from_secs(10)) // requests in progress are answered
.build()?
.run(|_worker| async {
let listener = TcpListener::bind("0.0.0.0:8080").expect("bind");
Server::new().serve(listener, handler).await;
})
}
Then run it:
cargo run --release # listens on port 8080
curl localhost:8080/health # ok
Each one runs from a clone of the repository; the crates' READMEs have more. examples/
A TCP echo server on every core.
cargo run --release --example echo
nc 127.0.0.1 7000A small HTTP/1.1 server: keep-alive, pipelining, idle timeouts, a header size limit and graceful shutdown on SIGINT and SIGTERM. The same routes the benchmarks use.
cargo run --release --example http
curl localhost:3006/jsonA UDP echo server, receiving with multishot recvmsg.
cargo run --release --example udp_echo
echo hello | nc -u -w1 127.0.0.1 7001Prints files to standard output, reading them through io_uring with positional reads.
cargo run --release --example cat -- Cargo.tomlEvery public item is documented, with an example where it helps.
Every error giong raises starts with a code, says what went wrong and how to fix it, and
links to its page. 81 codes so far. Match on giong::error::code(&err),
never on the message.
GIONG-E0102: no address found for db.internal. Fix: check the spelling of the name,
/etc/hosts, and the DNS servers in /etc/resolv.conf (in a container, the network it is
attached to). See https://github.com/giong-run/Giong/blob/main/docs/errors/E0102.md
| GIONG-E0001 | IoUringUnavailable | io_uring is not available |
| GIONG-E0002 | KernelTooOld | the kernel is too old |
| GIONG-E0003 | SignalsTaken | another runtime handles the signals |
| GIONG-E0004 | InvalidConfig | invalid runtime setting |
| GIONG-E0005 | Unexpected | unexpected result from the kernel |
| GIONG-E0006 | MixedReads | read used after recv |
| GIONG-E0007 | TimedOut | the time limit passed |
| GIONG-E0008 | NoSuchWorker | no such worker |
| GIONG-E0100 | InvalidAddress | invalid address |
| GIONG-E0101 | InvalidHostName | invalid host name |
| GIONG-E0102 | HostNotFound | host not found |
| GIONG-E0103 | NoAddresses | no address to use |
| GIONG-E0104 | NoDnsServer | no DNS server configured |
| GIONG-E0105 | DnsTimeout | DNS server did not answer |
| GIONG-E0106 | DnsServerFailure | DNS server failed |
| GIONG-E0107 | DnsBadResponse | malformed DNS answer |
| GIONG-E0200 | InvalidPath | invalid path |
| GIONG-E1101 | HttpClientRequest | invalid HTTP request |
| GIONG-E1102 | HttpClientConnect | cannot connect to the HTTP server |
| GIONG-E1103 | HttpClientTimeout | HTTP request timed out |
| GIONG-E1104 | HttpClientTooLarge | HTTP response too large |
| GIONG-E1105 | HttpClientRedirect | redirect not followed |
| GIONG-E1106 | HttpClientClosed | connection closed before the response |
| GIONG-E1107 | HttpClientProtocol | malformed HTTP response |
| GIONG-E1108 | HttpClientStatus | HTTP error status |
| GIONG-E1109 | HttpClientDecode | cannot decode the response body |
| GIONG-E1110 | HttpClientProxy | the HTTP proxy refused the request |
| GIONG-E1201 | WebInvalidRoute | invalid route pattern |
| GIONG-E1202 | WebDuplicateRoute | route added twice |
| GIONG-E1203 | WebNoRoute | no route for the path |
| GIONG-E1204 | WebMethodNotAllowed | method not allowed |
| GIONG-E1205 | WebBadParameter | invalid path or query parameter |
| GIONG-E1206 | WebNoSuchParameter | the route has no such parameter |
| GIONG-E1207 | WebBadBody | unreadable request body |
| GIONG-E1208 | WebUnsupportedMediaType | unsupported Content-Type |
| GIONG-E1209 | WebTimeout | no response in time |
| GIONG-E1210 | WebInternal | the handler failed |
| GIONG-E1211 | WebUnavailable | a service the handler needs is unavailable |
| GIONG-E1212 | WebCorsRejected | cross-origin request refused |
| GIONG-E1213 | WebConfig | invalid giong-web setting |
| GIONG-E2001 | NoTrustedRoots | no trusted certificate authorities |
| GIONG-E2002 | BadCertificateData | unreadable certificate data |
| GIONG-E2003 | InvalidServerName | invalid TLS server name |
| GIONG-E2004 | TlsCertificate | certificate rejected |
| GIONG-E2005 | TlsProtocol | TLS protocol error |
| GIONG-E2006 | TlsHandshakeTimeout | TLS handshake timed out |
| GIONG-E2007 | TlsHandshakeEof | connection closed during the TLS handshake |
| GIONG-E2008 | TlsBroken | TLS stream broken |
| GIONG-E3001 | PostgresConfig | invalid PostgreSQL configuration |
| GIONG-E3002 | PostgresConnect | cannot connect to PostgreSQL |
| GIONG-E3003 | PostgresAuth | PostgreSQL authentication failed |
| GIONG-E3004 | PostgresServer | PostgreSQL server error |
| GIONG-E3005 | PostgresType | PostgreSQL type mismatch |
| GIONG-E3006 | PostgresRowCount | wrong number of rows |
| GIONG-E3007 | PostgresTooLarge | PostgreSQL result too large |
| GIONG-E3008 | PostgresClosed | PostgreSQL connection closed |
| GIONG-E3009 | PostgresPoolTimeout | PostgreSQL pool wait timed out |
| GIONG-E3010 | PostgresProtocol | PostgreSQL protocol error |
| GIONG-E3011 | PostgresStatement | statement refused before sending |
| GIONG-E3101 | MysqlConfig | invalid MySQL configuration |
| GIONG-E3102 | MysqlConnect | cannot connect to MySQL |
| GIONG-E3103 | MysqlAuth | MySQL authentication failed |
| GIONG-E3104 | MysqlServer | MySQL server error |
| GIONG-E3105 | MysqlType | MySQL type mismatch |
| GIONG-E3106 | MysqlRowCount | wrong number of rows |
| GIONG-E3107 | MysqlTooLarge | MySQL result too large |
| GIONG-E3108 | MysqlClosed | MySQL connection closed |
| GIONG-E3109 | MysqlPoolTimeout | MySQL pool wait timed out |
| GIONG-E3110 | MysqlProtocol | MySQL protocol error |
| GIONG-E3111 | MysqlStatement | statement refused before sending |
| GIONG-E3201 | RedisConfig | invalid Redis configuration |
| GIONG-E3202 | RedisConnect | cannot connect to Redis |
| GIONG-E3203 | RedisAuth | Redis authentication failed |
| GIONG-E3204 | RedisServer | Redis server error |
| GIONG-E3205 | RedisType | Redis type mismatch |
| GIONG-E3206 | RedisCommand | command refused before sending |
| GIONG-E3207 | RedisTooLarge | Redis reply too large |
| GIONG-E3208 | RedisClosed | Redis connection closed |
| GIONG-E3209 | RedisPoolTimeout | Redis pool wait timed out |
| GIONG-E3210 | RedisProtocol | Redis protocol error |
| GIONG-E3211 | RedisTimeout | Redis reply timed out |
Generated from docs/errors/README.md
Kernel 6.0 or newer. An epoll driver for machines where io_uring is blocked is on the roadmap; there will be no kqueue or IOCP in production.
Crates that need the Tokio runtime (hyper, sqlx, reqwest) do not run on giong. Crates that only use std::future do.
giong-http speaks HTTP/1.1. A request body over the limit is refused.
TLS runs in user space on rustls, and certificates are not reloaded for you.
New work can go to the least busy worker (spawn_balanced, bind_balanced), but a task never moves once it has started.
Names come from /etc/hosts and DNS, not mDNS or LDAP. Also missing: Unix datagram sockets, multicast, file locks.
Monoio is the mature choice and runs in production at ByteDance. If you need HTTP/2 or Tokio-compatible crates today, use it.
Glommio is built for storage engines: Direct I/O and priority scheduling are its strengths.
Tokio is the general-purpose runtime. giong is not trying to replace it for every workload.
Not yet. It is complete enough to write real services and is tested hard, but it has not run in production. 1.0 waits for, among other things, at least one production user reporting back.
No. io_uring is a Linux interface. On Windows use WSL2 with a 6.x kernel (uname -r; wsl --update if it is older); on macOS a Linux virtual machine. In Docker, allow io_uring as docs/DEPLOYMENT.md shows.
6.0 or newer, 6.1 or newer recommended. giong tries three ring setups in order: DEFER_TASKRUN (6.1+), COOP_TASKRUN (6.0), then no flags.
Not crates that need the Tokio runtime; giong has its own HTTP, TLS, PostgreSQL, MySQL and Redis crates instead. Crates that only use std::future work. Adapters for the futures-io and Tokio I/O traits are on the roadmap.
Sometimes, and the benchmarks page says where. Small responses at 50 connections are a tie. giong makes about 0.03 system calls per request against 2.05, spends the least CPU per request at 5,000 connections, and reads files 5.5 times faster than Tokio on one core. Every number is over loopback on one machine.
Privately, through GitHub's private vulnerability reporting (the Security link at the bottom of every page), not in a public issue.
After Thánh Gióng, the child of Vietnamese legend who lay silent for three years and then rose a giant: next to nothing while idle, every core the moment load arrives.
Read CONTRIBUTING.md first; coding agents have AGENTS.md. Open an issue before anything larger than a fix.
git clone https://github.com/giong-run/Giong.git && cd Giong
cargo test --workspace --all-features # the whole suite, every crate