Skip to content

Commit d58c57b

Browse files
committed
TCP server example
1 parent 293c144 commit d58c57b

File tree

1 file changed

+60
-0
lines changed

1 file changed

+60
-0
lines changed

docs/examples/tcpserver.nim

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
## Simple TCP/IP server that accepts both IPv4 and IPv6 connections
2+
import chronos
3+
4+
# Because handleConn runs as an indepented task via `asyncSpawn`, it must
5+
# handle all errors on its own (or the application will crash)
6+
proc handleConn(transport: StreamTransport, done: Future[void]) {.
7+
async: (raises: []).} =
8+
# Handle a single remote connection
9+
try:
10+
echo "Incoming connection from ", transport.remoteAddress()
11+
12+
while true:
13+
# Read and echo back lines until `q` or `0` is entered
14+
let data = await transport.readLine(sep="\n")
15+
if data.len > 0:
16+
if data[0] == 'q':
17+
if not done.finished():
18+
# Notify server that it's time to stop - some other client could
19+
# have done this already, so we check with `finished` first
20+
done.complete()
21+
break
22+
elif data[0] == '0':
23+
break # Stop reading and close the connection
24+
25+
echo "Echoed ", await transport.write(data & "\n"), " bytes"
26+
except CancelledError:
27+
raiseAssert "No cancellations in this example"
28+
except TransportError as exc:
29+
echo "Connection problem! ", exc.msg
30+
finally:
31+
# Connections must always be closed to avoid resource leaks
32+
await transport.closeWait()
33+
34+
proc myApp(server: StreamServer) {.async.} =
35+
echo "Accepting connections on ", server.local
36+
let done = Future[void].init()
37+
try:
38+
while true:
39+
let
40+
accept = server.accept()
41+
42+
# Wait either for a new connection or that an existing connection signals
43+
# that it's time to stop
44+
discard await race(accept, done)
45+
if done.finished(): break
46+
47+
# asyncSpawn is used to spawn an independent async task that runs until
48+
# it's finished without blocking the current async function - the OS will
49+
# clean up these tasks on shutdown but a long-running server will want to
50+
# collect them and make sure their associated sockets are closed properly
51+
asyncSpawn handleConn(accept.read(), done)
52+
finally:
53+
await server.closeWait()
54+
55+
let
56+
# This server listens on both IPv4 and IPv6 and will pick a port number by
57+
# itself
58+
server = createStreamServer(AnyAddress6)
59+
60+
waitFor myApp(server)

0 commit comments

Comments
 (0)