tnewasyncudp.nim 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. discard """
  2. output: "5000"
  3. """
  4. import asyncdispatch, nativesockets, net, strutils, os
  5. when defined(windows):
  6. import winlean
  7. else:
  8. import posix
  9. var msgCount = 0
  10. var recvCount = 0
  11. const
  12. messagesToSend = 100
  13. swarmSize = 50
  14. serverPort = 10333
  15. var
  16. sendports = 0
  17. recvports = 0
  18. proc saveSendingPort(port: int) =
  19. sendports = sendports + port
  20. proc saveReceivedPort(port: int) =
  21. recvports = recvports + port
  22. proc prepareAddress(intaddr: uint32, intport: uint16): ptr Sockaddr_in =
  23. result = cast[ptr Sockaddr_in](alloc0(sizeof(Sockaddr_in)))
  24. result.sin_family = typeof(result.sin_family)(toInt(nativesockets.AF_INET))
  25. result.sin_port = nativesockets.htons(intport)
  26. result.sin_addr.s_addr = nativesockets.htonl(intaddr)
  27. proc launchSwarm(name: ptr SockAddr) {.async.} =
  28. var i = 0
  29. var k = 0
  30. var buffer: array[16384, char]
  31. var slen = sizeof(Sockaddr_in).SockLen
  32. var saddr = Sockaddr_in()
  33. while i < swarmSize:
  34. var peeraddr = prepareAddress(INADDR_LOOPBACK, 0)
  35. var sock = createAsyncNativeSocket(nativesockets.AF_INET,
  36. nativesockets.SOCK_DGRAM,
  37. Protocol.IPPROTO_UDP)
  38. if bindAddr(sock.SocketHandle, cast[ptr SockAddr](peeraddr),
  39. sizeof(Sockaddr_in).Socklen) < 0'i32:
  40. raiseOSError(osLastError())
  41. let sockport = getSockName(sock.SocketHandle).int
  42. k = 0
  43. while k < messagesToSend:
  44. zeroMem(addr(buffer[0]), 16384)
  45. zeroMem(cast[pointer](addr(saddr)), sizeof(Sockaddr_in))
  46. var message = "Message " & $(i * messagesToSend + k)
  47. await sendTo(sock, addr message[0], len(message),
  48. name, sizeof(Sockaddr_in).SockLen)
  49. var size = await recvFromInto(sock, cast[pointer](addr buffer[0]),
  50. 16384, cast[ptr SockAddr](addr saddr),
  51. addr slen)
  52. size = 0
  53. var grammString = $cstring(addr buffer)
  54. if grammString == message:
  55. saveSendingPort(sockport)
  56. inc(recvCount)
  57. inc(k)
  58. closeSocket(sock)
  59. inc(i)
  60. proc readMessages(server: AsyncFD) {.async.} =
  61. var buffer: array[16384, char]
  62. var slen = sizeof(Sockaddr_in).SockLen
  63. var saddr = Sockaddr_in()
  64. var maxResponses = (swarmSize * messagesToSend)
  65. var i = 0
  66. while i < maxResponses:
  67. zeroMem(addr(buffer[0]), 16384)
  68. zeroMem(cast[pointer](addr(saddr)), sizeof(Sockaddr_in))
  69. var size = await recvFromInto(server, cast[cstring](addr buffer[0]),
  70. 16384, cast[ptr SockAddr](addr(saddr)),
  71. addr(slen))
  72. size = 0
  73. var grammString = $cstring(addr buffer)
  74. if grammString.startswith("Message ") and
  75. saddr.sin_addr.s_addr == nativesockets.ntohl(INADDR_LOOPBACK.uint32):
  76. await sendTo(server, addr grammString[0], len(grammString),
  77. cast[ptr SockAddr](addr saddr), slen)
  78. inc(msgCount)
  79. saveReceivedPort(nativesockets.ntohs(saddr.sin_port).int)
  80. inc(i)
  81. proc createServer() {.async.} =
  82. var name = prepareAddress(INADDR_LOOPBACK, serverPort)
  83. var server = createAsyncNativeSocket(nativesockets.AF_INET,
  84. nativesockets.SOCK_DGRAM,
  85. Protocol.IPPROTO_UDP)
  86. if bindAddr(server.SocketHandle, cast[ptr SockAddr](name),
  87. sizeof(Sockaddr_in).Socklen) < 0'i32:
  88. raiseOSError(osLastError())
  89. asyncCheck readMessages(server)
  90. var name = prepareAddress(INADDR_LOOPBACK, serverPort) # 127.0.0.1
  91. asyncCheck createServer()
  92. asyncCheck launchSwarm(cast[ptr SockAddr](name))
  93. while true:
  94. poll()
  95. if recvCount == swarmSize * messagesToSend:
  96. break
  97. assert msgCount == swarmSize * messagesToSend
  98. assert sendports == recvports
  99. echo msgCount