nimble install netty
Netty is a reliable connection over UDP aimed at games. Normally UDP packets can get duplicated, dropped, or come out of order. Netty makes sure packets are not duplicated, re-sends them if they get dropped, and all packets come in order. UDP packets might also get split if they are above 512 bytes and also can fail to be sent if they are bigger than 1-2k. Netty breaks up big packets and sends them in pieces making sure each piece comes reliably in order. Finally sometimes it is impossible for two clients to communicate directly with TCP because of NATs, but Netty can send hole punch probes to help them connect.
API reference: https://treeform.github.io/netty
TCP is really bad for short latency sensitive messages. TCP was designed for throughput (downloading files) not latency (games). Netty will resend stuff faster than TCP, Netty will not buffer and you also get NAT punch-through probes (which TCP does not have). Netty is basically "like TCP but for games". You should not be using Netty if you will be sending large amounts of data. By default Netty is capped at 250KB of data in flight (reactor.maxInFlight, configurable).
| feature | TCP | UDP | Netty |
|---|---|---|---|
| designed for low latency | no | yes | yes |
| designed for throughput | yes | no | no |
| packet framing | no | yes | yes |
| packet ordering | yes | no | yes |
| packet splitting | yes | no | yes |
| packet retry | yes | no | yes |
| packet deduplication | yes | no | yes |
| hole punch through | no | yes | yes |
| connection handling | yes | no | yes |
| congestion control | yes | no | no |
| fixed in-flight byte cap | no | no | yes |
import netty
# listen for a connection on localhost port 1999var server =newReactor("127.0.0.1", 1999)
echo"Listening for UDP on 127.0.0.1:1999"# main loopwhiletrue:
# must call tick to both read and write
server.tick()
# usually there are no new messages, but if there arefor msg in server.messages:
# print message dataecho"GOT MESSAGE: ", msg.data
# echo message back to the client
server.send(msg.conn, "you said:"& msg.data)import netty
# create connectionvar client =newReactor()
# connect to servervar c2s = client.connect("127.0.0.1", 1999)
# send message on the connection
client.send(c2s, "hi")
# main loopwhiletrue:
# must call tick to both read and write
client.tick()
# usually there are no new messages, but if there arefor msg in client.messages:
# print message dataecho"GOT MESSAGE: ", msg.dataimport netty
var server =newReactor("127.0.0.1", 2001)
echo"Listening for UDP on 127.0.0.1:2001"whiletrue:
server.tick()
for connection in server.newConnections:
echo"[new] ", connection.address
for connection in server.deadConnections:
echo"[dead] ", connection.address
for msg in server.messages:
echo"[msg]", msg.data
# send msg data to all connectionsfor connection in server.connections:
server.send(connection, msg.data)import netty
var client =newReactor()
var connection = client.connect("127.0.0.1", 2001)
# get persons nameecho"what is your name?"var name =readLine(stdin)
echo"note: press enter to see if people sent you things"whiletrue:
client.tick()
for msg in client.messages:
echo msg.data
# wait for user to type a linelet line =readLine(stdin)
if line.len >0:
client.send(connection, name &":"& line)