discard """ output: "5000" """ import asyncdispatch, nativesockets, net, strutils, os when defined(windows): import winlean else: import posix var msgCount = 0 var recvCount = 0 const messagesToSend = 100 swarmSize = 50 serverPort = 10333 var sendports = 0 recvports = 0 proc saveSendingPort(port: int) = sendports = sendports + port proc saveReceivedPort(port: int) = recvports = recvports + port proc prepareAddress(intaddr: uint32, intport: uint16): ptr Sockaddr_in = result = cast[ptr Sockaddr_in](alloc0(sizeof(Sockaddr_in))) result.sin_family = toInt(nativesockets.AF_INET).uint16 result.sin_port = nativesockets.htons(intport) result.sin_addr.s_addr = nativesockets.htonl(intaddr) proc launchSwarm(name: ptr SockAddr) {.async.} = var i = 0 var k = 0 var buffer: array[16384, char] var slen = sizeof(Sockaddr_in).SockLen var saddr = Sockaddr_in() while i < swarmSize: var peeraddr = prepareAddress(INADDR_LOOPBACK, 0) var sock = newAsyncNativeSocket(nativesockets.AF_INET, nativesockets.SOCK_DGRAM, Protocol.IPPROTO_UDP) if bindAddr(sock.SocketHandle, cast[ptr SockAddr](peeraddr), sizeof(Sockaddr_in).Socklen) < 0'i32: raiseOSError(osLastError()) let sockport = getSockName(sock.SocketHandle).int k = 0 while k < messagesToSend: zeroMem(addr(buffer[0]), 16384) zeroMem(cast[pointer](addr(saddr)), sizeof(Sockaddr_in)) var message = "Message " & $(i * messagesToSend + k) await sendTo(sock, addr message[0], len(message), name, sizeof(Sockaddr_in).SockLen) var size = await recvFromInto(sock, cast[pointer](addr buffer[0]), 16384, cast[ptr SockAddr](addr saddr), addr slen) size = 0 var grammString = $cstring(addr buffer) if grammString == message: saveSendingPort(sockport) inc(recvCount) inc(k) closeSocket(sock) inc(i) proc readMessages(server: AsyncFD) {.async.} = var buffer: array[16384, char] var slen = sizeof(Sockaddr_in).SockLen var saddr = Sockaddr_in() var maxResponses = (swarmSize * messagesToSend) var i = 0 while i < maxResponses: zeroMem(addr(buffer[0]), 16384) zeroMem(cast[pointer](addr(saddr)), sizeof(Sockaddr_in)) var size = await recvFromInto(server, cast[cstring](addr buffer[0]), 16384, cast[ptr SockAddr](addr(saddr)), addr(slen)) size = 0 var grammString = $cstring(addr buffer) if grammString.startswith("Message ") and saddr.sin_addr.s_addr == nativesockets.ntohl(INADDR_LOOPBACK.uint32): await sendTo(server, addr grammString[0], len(grammString), cast[ptr SockAddr](addr saddr), slen) inc(msgCount) saveReceivedPort(nativesockets.ntohs(saddr.sin_port).int) inc(i) proc createServer() {.async.} = var name = prepareAddress(INADDR_LOOPBACK, serverPort) var server = newAsyncNativeSocket(nativesockets.AF_INET, nativesockets.SOCK_DGRAM, Protocol.IPPROTO_UDP) if bindAddr(server.SocketHandle, cast[ptr SockAddr](name), sizeof(Sockaddr_in).Socklen) < 0'i32: raiseOSError(osLastError()) asyncCheck readMessages(server) var name = prepareAddress(INADDR_LOOPBACK, serverPort) # 127.0.0.1 asyncCheck createServer() asyncCheck launchSwarm(cast[ptr SockAddr](name)) while true: poll() if recvCount == swarmSize * messagesToSend: break assert msgCount == swarmSize * messagesToSend assert sendports == recvports echo msgCount