123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081 |
- ;; ==========
- ;; TCP CLIENT
- ;; ==========
- ;; This TCP client connects to a server and sends it a message.
- (define-module (tcp-client)
- #:export (run-client
- display-message-handler
- display-message-protocol
- make-client-protocol))
- (use-modules (ice-9 binary-ports)
- (ice-9 textual-ports)
- (rnrs bytevectors)
- (networking-lib helpers)
- (json))
- #;(define receive-buffer (make-bytevector 1024))
- (define (connect-to-server address port)
- (let ([sock
- ;; create a TCP socket
- (socket PF_INET SOCK_STREAM
- (protoent:proto (getprotobyname "TCP")))])
- ;; connect to somewhere
- ;; CONNECT: ARGUMENTS:
- ;; 1. the socket to use
- ;; 2. the protocol family
- ;; 3. the address to connect to
- ;; 4. the port on which to connect
- (connect sock
- (make-socket-address AF_INET
- address
- 12345))
- sock))
- (define (handle-server-messages in-out-sock protocol)
- (display "INFO: now handling messages from server according to protocol\n")
- (protocol in-out-sock))
- (define (display-message-handler in-out-sock message)
- (display (simple-format #f "RECEIVED: ~s\n" message)))
- #;(define (close-socket in-out-sock)
- (display (simple-format #f "~s\n" "EOF received. Closing socket ..."))
- (close in-out-sock)
- (display (simple-format #f "~s\n" "Socket closed.")))
- (define* (run-client port #:key (protocol display-message-protocol))
- (define in-out-sock (connect-to-server INADDR_LOOPBACK port))
- ;; send greeting
- #;(put-string in-out-sock "Hello from client!\n")
- ;; react on messages inside another thread to keep responsive
- (call-with-new-thread
- (λ ()
- (handle-server-messages in-out-sock protocol)))
- ;; return in-out-sock to be able to close it from REPL
- in-out-sock)
- (define* (make-client-protocol
- #:key
- (port-reader get-line)
- (message-handler display-message-handler)
- (eof-handler close))
- "A client protocol is initialized with an input output socket. "
- "The socket cannot be specified ahead of time, since it is created by the client, "
- "when the client connects to the server and not earlier. "
- "It the client protocol will handle messages from the socket according to its implementation."
- (λ (in-out-sock)
- ;; Handle infinitely many messages.
- (while (not (port-closed? in-out-sock))
- ;; Receiving a message is blocking.
- ;; It should not lead to a high CPU usage.
- (let ([received-data (port-reader in-out-sock)])
- (cond [(eof-object? received-data)
- (eof-handler in-out-sock)
- (break)]
- [else
- (message-handler in-out-sock received-data)])))))
- (define display-message-protocol (make-client-protocol))
|