Last active
September 1, 2021 13:46
-
-
Save kaushalmodi/e75bd98468e75b6efdd7e2268bc68596 to your computer and use it in GitHub Desktop.
Nim client/server protobuf
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import std/[os, threadpool, strformat, asyncdispatch, asyncnet] | |
import protocol_protobuf, streams | |
proc connect(socket: AsyncSocket, serverAddr: string) {.async.} = | |
echo &"Connecting to {serverAddr}" | |
await socket.connect(serverAddr, Port(7687)) | |
echo "Connected!" | |
echo "Chat application started" | |
if paramCount() < 1: | |
quit("Please specify the server address and username, e.g. ./client localhost") | |
let | |
serverAddr = paramStr(1) | |
var | |
socket = newAsyncSocket() | |
asyncCheck connect(socket, serverAddr) | |
proc sendMessages() {.async.} = | |
var | |
(msg, msgLen) = createProtoMessage() | |
var | |
stream = newStringStream() | |
stream.write msg | |
echo "size of stream = ", sizeof(stream) | |
await socket.send(addr stream, sizeof(stream)) | |
waitFor sendMessages() | |
# (1) First start the server in one terminal | |
# (2) *Then* run the client in another terminal, otherwise you will | |
# get "Software caused connection abort" exception. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import protobuf | |
# Define our protobuf specification and generate Nim code to use it | |
const protoSpec = """ | |
syntax = "proto3"; | |
message ExampleMessage { | |
int32 number = 1; | |
string text = 2; | |
} | |
""" | |
parseProto(protoSpec) | |
# Create our message | |
var msg = new ExampleMessage | |
msg.number = 10 | |
msg.text = "Hello world" | |
# Make the ExampleMessage type visible in modules where this module is imported. | |
exportMessage ExampleMessage | |
proc createProtoMessage*(): (ExampleMessage, int) = | |
(msg, msg.len) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import std/[asyncdispatch, asyncnet, strformat] | |
import protocol_protobuf, streams | |
type | |
Client = ref object | |
socket: AsyncSocket | |
netAddr: string | |
id: int | |
connected: bool | |
Server = ref object | |
socket: AsyncSocket | |
clients: seq[Client] | |
proc newServer(): Server = | |
Server(socket: newAsyncSocket(), clients: @[]) | |
proc `$`(c: Client): string = | |
&"{c.id} ({c.netAddr})" | |
var | |
server = newServer() | |
proc processMessages(s: Server, c: Client) {.async.} = | |
while true: | |
var | |
msgStream = newStringStream() | |
let | |
numBytes = await c.socket.recvInto(addr msgStream, 8) | |
echo "num bytes received = ", numBytes | |
if numBytes == 0: | |
echo &"{c} disconnected!" | |
c.connected = false | |
c.socket.close() | |
return | |
msgStream.setPosition(0) | |
var | |
msg = msgStream.readExampleMessage() | |
echo &"{c} sent: number = {msg.number}, text = {msg.text}" | |
proc loop(s: Server; port = 7687) {.async.} = | |
s.socket.bindAddr(Port(port)) | |
s.socket.listen() | |
while true: | |
let | |
(netAddr, clientSocket) = await s.socket.acceptAddr() | |
echo &"Accepted connection from {netAddr}" | |
let | |
c = Client(socket: clientSocket, | |
netAddr: netAddr, | |
id: s.clients.len, | |
connected: true) | |
s.clients.add(c) | |
asyncCheck processMessages(s, c) | |
waitFor loop(server) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment