tasynceagain.nim 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. discard """
  2. disabled: "windows"
  3. exitcode: 0
  4. """
  5. # AsyncSocketBug.nim
  6. # Jens Alfke (@snej) -- 16 July 2020
  7. # Demonstrates data loss by Nim's AsyncSocket.
  8. # Just run it, and it will raise an assertion failure within a minute.
  9. import asyncdispatch, asyncnet, strformat, strutils, sugar
  10. const FrameSize = 9999 # Exact size not important, but larger sizes fail quicker
  11. proc runServer() {.async.} =
  12. # Server side:
  13. var server = newAsyncSocket()
  14. server.bindAddr(Port(9001))
  15. server.listen()
  16. let client = await server.accept()
  17. echo "Server got client connection"
  18. var lastN = 0
  19. while true:
  20. let frame = await client.recv(FrameSize)
  21. doAssert frame.len == FrameSize
  22. let n = frame[0..<6].parseInt()
  23. echo "RCVD #", n, ": ", frame[0..80], "..."
  24. if n != lastN + 1:
  25. echo &"******** ERROR: Server received #{n}, but last was #{lastN}!"
  26. doAssert n == lastN + 1
  27. lastN = n
  28. await sleepAsync 100
  29. proc main() {.async.} =
  30. asyncCheck runServer()
  31. # Client side:
  32. let socket = newAsyncSocket(buffered = false)
  33. await socket.connect("localhost", Port(9001))
  34. echo "Client socket connected"
  35. var sentCount = 0
  36. var completedCount = 0
  37. while sentCount < 2000:
  38. sentCount += 1
  39. let n = sentCount
  40. var message = &"{n:06} This is message #{n} of ∞. Please stay tuned for more. "
  41. #echo ">>> ", message
  42. while message.len < FrameSize:
  43. message = message & message
  44. let frame = message[0..<FrameSize]
  45. capture n:
  46. socket.send(frame).addCallback proc(f: Future[void]) =
  47. # Callback when the send completes:
  48. assert not f.failed
  49. echo "SENT #", n
  50. if n != completedCount + 1:
  51. echo &"******** ERROR: Client completed #{n}, but last completed was #{completedCount}!"
  52. # If this assert is enabled, it will trigger earlier than the server-side assert above:
  53. assert n == completedCount + 1
  54. completedCount = n
  55. await sleepAsync 1
  56. waitFor main()