mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-29 17:34:43 +00:00
89 lines
2.8 KiB
Nim
89 lines
2.8 KiB
Nim
discard """
|
|
action: compile
|
|
"""
|
|
|
|
import asyncdispatch, asyncnet
|
|
|
|
type
|
|
Client = ref object
|
|
socket: AsyncSocket
|
|
netAddr: string
|
|
id: int
|
|
connected: bool
|
|
|
|
Server = ref object
|
|
socket: AsyncSocket
|
|
clients: seq[Client]
|
|
|
|
proc newServer(): Server =
|
|
## Constructor for creating a new ``Server``.
|
|
Server(socket: newAsyncSocket(), clients: @[])
|
|
|
|
proc `$`(client: Client): string =
|
|
## Converts a ``Client``'s information into a string.
|
|
$client.id & "(" & client.netAddr & ")"
|
|
|
|
proc processMessages(server: Server, client: Client) {.async.} =
|
|
## Loops while ``client`` is connected to this server, and checks
|
|
## whether as message has been received from ``client``.
|
|
while true:
|
|
# Pause execution of this procedure until a line of data is received from
|
|
# ``client``.
|
|
let line = await client.socket.recvLine()
|
|
|
|
# The ``recvLine`` procedure returns ``""`` (i.e. a string of length 0)
|
|
# when ``client`` has disconnected.
|
|
if line.len == 0:
|
|
echo(client, " disconnected!")
|
|
client.connected = false
|
|
# When a socket disconnects it must be closed.
|
|
client.socket.close()
|
|
return
|
|
|
|
# Display the message that was sent by the client.
|
|
echo(client, " sent: ", line)
|
|
|
|
# Send the message to other clients.
|
|
for c in server.clients:
|
|
# Don't send it to the client that sent this or to a client that is
|
|
# disconnected.
|
|
if c.id != client.id and c.connected:
|
|
await c.socket.send(line & "\c\l")
|
|
|
|
proc loop(server: Server, port = 7687) {.async.} =
|
|
## Loops forever and checks for new connections.
|
|
|
|
# Bind the port number specified by ``port``.
|
|
server.socket.bindAddr(port.Port)
|
|
# Ready the server socket for new connections.
|
|
server.socket.listen()
|
|
echo("Listening on localhost:", port)
|
|
|
|
while true:
|
|
# Pause execution of this procedure until a new connection is accepted.
|
|
let (netAddr, clientSocket) = await server.socket.acceptAddr()
|
|
echo("Accepted connection from ", netAddr)
|
|
|
|
# Create a new instance of Client.
|
|
let client = Client(
|
|
socket: clientSocket,
|
|
netAddr: netAddr,
|
|
id: server.clients.len,
|
|
connected: true
|
|
)
|
|
# Add this new instance to the server's list of clients.
|
|
server.clients.add(client)
|
|
# Run the ``processMessages`` procedure asynchronously in the background,
|
|
# this procedure will continuously check for new messages from the client.
|
|
asyncCheck processMessages(server, client)
|
|
|
|
# Check whether this module has been imported as a dependency to another
|
|
# module, or whether this module is the main module.
|
|
when true:
|
|
# Initialise a new server.
|
|
var server = newServer()
|
|
echo("Server initialised!")
|
|
# Execute the ``loop`` procedure. The ``waitFor`` procedure will run the
|
|
# asyncdispatch event loop until the ``loop`` procedure finishes executing.
|
|
waitFor loop(server)
|