Hello,
I have managed to get another case of a binding not being available
according to the Guile REPL, this time I have the code and way to
reproduce the issue.
After some struggling, trying and reading the docs of networking
procedures multiple times, I managed to write a little TCP server and
client example program.
(More examples in this area would be cool and if my code is worth
anything, feel free to take it, improve it, and make an example for TCP
server/client in the docs. Or maybe I can put examples in the docs?)
The directory structure looks as follows (tree):
.
├── main.scm
├── networking-lib
│ └── helpers.scm
├── tcp-client.scm
└── tcp-server.scm
The contents of the files are:
;; ===== HELPERS MODULE (networking-lib/helpers.scm) =====
(use-modules (rnrs bytevectors))
(define-module (networking-lib helpers)
#:export (display-byte-vector))
(define (display-byte-vector vec len)
(let ([minimal-vec (make-bytevector len)])
(bytevector-copy! vec 0 minimal-vec 0 len)
(display (simple-format #f
"I got the following message: ~s\n"
(utf8->string minimal-vec)))))
;; ===== HELPERS MODULE END =====
;; ===== CLIENT (tcp-client.scm) =====
(add-to-load-path
(string-append "/home/xiaolong"
"/development/Guile"
"/examples-and-convenience-procedures/network-programming"))
(use-modules (rnrs bytevectors)
(networking-lib helpers))
(define receive-buffer (make-bytevector 1024))
(define (connect-to-server)
(let ([sock
(socket PF_INET SOCK_STREAM
(protoent:proto (getprotobyname "TCP")))])
(connect sock
(make-socket-address AF_INET
INADDR_LOOPBACK
12345))
sock))
(define (send-message-to-server sock message)
(display (simple-format #f "sending message to server: ~s" message))
(send sock (string->utf8 message)))
(define (receive-message-from-server! sock receive-buffer)
(recv! sock receive-buffer))
(define in-out-sock (connect-to-server))
(let ([bytes-count (receive-message-from-server! in-out-sock
receive-buffer)])
(display-byte-vector receive-buffer bytes-count)
(send-message-to-server in-out-sock "Hello from client!\n"))
;; ===== CLIENT END =====
;; ===== SERVER (tcp-server.scm) =====
(add-to-load-path
(string-append "/home/user"
"/development/Guile"
"/examples-and-convenience-procedures/network-programming"))
(use-modules (rnrs bytevectors)
(networking-lib helpers)
(ice-9 threads))
(define receive-buffer (make-bytevector 1024))
(define (create-server-socket)
(let ([sock
(socket PF_INET SOCK_STREAM (protoent:proto (getprotobyname
"TCP")))]
[backlog-of-connection-requests 10])
(bind sock (make-socket-address AF_INET INADDR_ANY 12345))
(listen sock backlog-of-connection-requests)
sock))
(define (send-message-to-client sock message)
(display (simple-format #f "sending message to client: ~s\n" message))
(send sock (string->utf8 message)))
(define (handle-messages sock)
(call-with-new-thread
(λ ()
(while #t
(let* ([client-connection
(accept sock)]
[client-details (cdr client-connection)]
[in-out-sock (car client-connection)])
(display
(simple-format #f
"Got new client connection: ~S\n"
client-details))
(display
(simple-format #f
"Client address: ~S\n"
(gethostbyaddr (sockaddr:addr client-details))))
(send-message-to-client in-out-sock "Hello from server!\n")
(display-byte-vector receive-buffer (recv! in-out-sock
receive-buffer))
(display "closing input-output-socket with client ...\n"))))))
(define sock (create-server-socket))
(handle-messages sock)
;; ===== SERVER END =====
With that code, I do the following:
1. Start two Guile REPLs inside the
.../examples-and-convenience-procedures/network-programming directory.
(in XFCE4 terminal)
2. In the first REPL I paste all code of the server. It starts a new
thread and runs fine without showing any error.
3. In the second REPL I paste all code of the client. It seems to run
fine until I hit the last let form.
The error I get is:
;; ===== ERROR =====
scheme@(guile-user)> (let ([bytes-count (receive-message-from-server!
in-out-sock receive-buffer)])
... (display-byte-vector receive-buffer bytes-count)
... (send-message-to-server in-out-sock "Hello from client!\n"))
networking-lib/helpers.scm:7:0: In procedure display-byte-vector:
In procedure module-lookup: Unbound variable: make-bytevector
Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue.
scheme@(guile-user) [1]>
;; ===== ERROR END =====
But I did import bytevectors in helpers.scm! How can it not find that?
When I paste the procedure defined in helpers.scm into the server and
client programs and do not use the helpers module, it seem to work just
fine.
Is it impossible to use modules inside the helpers module, which are
already used code, which uses the helper module (rnrs bytevectors)?
Regards,
Zelphir