tcp-client.scm 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. ;; ==========
  2. ;; TCP CLIENT
  3. ;; ==========
  4. ;; This TCP client connects to a server and sends it a message.
  5. (define-module (tcp-client)
  6. #:export (run-client
  7. display-message-handler
  8. display-message-protocol
  9. make-client-protocol))
  10. (use-modules (ice-9 binary-ports)
  11. (ice-9 textual-ports)
  12. (rnrs bytevectors)
  13. (networking-lib helpers)
  14. (json))
  15. #;(define receive-buffer (make-bytevector 1024))
  16. (define (connect-to-server address port)
  17. (let ([sock
  18. ;; create a TCP socket
  19. (socket PF_INET SOCK_STREAM
  20. (protoent:proto (getprotobyname "TCP")))])
  21. ;; connect to somewhere
  22. ;; CONNECT: ARGUMENTS:
  23. ;; 1. the socket to use
  24. ;; 2. the protocol family
  25. ;; 3. the address to connect to
  26. ;; 4. the port on which to connect
  27. (connect sock
  28. (make-socket-address AF_INET
  29. address
  30. 12345))
  31. sock))
  32. (define (handle-server-messages in-out-sock protocol)
  33. (display "INFO: now handling messages from server according to protocol\n")
  34. (protocol in-out-sock))
  35. (define (display-message-handler in-out-sock message)
  36. (display (simple-format #f "RECEIVED: ~s\n" message)))
  37. #;(define (close-socket in-out-sock)
  38. (display (simple-format #f "~s\n" "EOF received. Closing socket ..."))
  39. (close in-out-sock)
  40. (display (simple-format #f "~s\n" "Socket closed.")))
  41. (define* (run-client port #:key (protocol display-message-protocol))
  42. (define in-out-sock (connect-to-server INADDR_LOOPBACK port))
  43. ;; send greeting
  44. #;(put-string in-out-sock "Hello from client!\n")
  45. ;; react on messages inside another thread to keep responsive
  46. (call-with-new-thread
  47. (λ ()
  48. (handle-server-messages in-out-sock protocol)))
  49. ;; return in-out-sock to be able to close it from REPL
  50. in-out-sock)
  51. (define* (make-client-protocol
  52. #:key
  53. (port-reader get-line)
  54. (message-handler display-message-handler)
  55. (eof-handler close))
  56. "A client protocol is initialized with an input output socket. "
  57. "The socket cannot be specified ahead of time, since it is created by the client, "
  58. "when the client connects to the server and not earlier. "
  59. "It the client protocol will handle messages from the socket according to its implementation."
  60. (λ (in-out-sock)
  61. ;; Handle infinitely many messages.
  62. (while (not (port-closed? in-out-sock))
  63. ;; Receiving a message is blocking.
  64. ;; It should not lead to a high CPU usage.
  65. (let ([received-data (port-reader in-out-sock)])
  66. (cond [(eof-object? received-data)
  67. (eof-handler in-out-sock)
  68. (break)]
  69. [else
  70. (message-handler in-out-sock received-data)])))))
  71. (define display-message-protocol (make-client-protocol))