On Thu, 21 Jun 2018 08:22:36 +0200 Zelphir Kaltstahl <zelphirkaltst...@gmail.com> wrote: > Hello Guile users, > > I wrote some TCP server and client in Guile which I have uploaded here: > > https://gitlab.com/zelphir-kaltstahl-projects/guile-scheme-tutorials-and-examples/raw/dev/network-programming/tcp-client.scm > > and here: > > https://gitlab.com/zelphir-kaltstahl-projects/guile-scheme-tutorials-and-examples/raw/dev/network-programming/tcp-server.scm > > or normal GitLab view: > > https://gitlab.com/zelphir-kaltstahl-projects/guile-scheme-tutorials-and-examples/tree/dev/network-programming > > (Is it OK to post these as links, or always better to include all > relevant source code on the mailing list? On other e-mail lists I have > experienced that my message was too long and got truncated, so I posted > the code as links to the raw file on GitLab.) > > The loop for reacting on messages from a client on the server looks like > this: > > (while #t > (let* ([bytes-count (recv! in-out-sock receive-buffer)] > [message-received (byte-vector->utf8-message receive-buffer > bytes-count)]) > (message-handler client-connection message-received)))))) > > But this has a problem: When I run both client and server in two > terminals and then exit the client using Ctrl-D, the server somehow gets > stuck in the loop always receiving the empty string. Since that is 0 > Bytes long, it does not really take anything from the socket (if I > understand correctly), but instead can recv! in the next iteration again > immediately. The only thing that works then for stopping this loop is to > hold down Ctrl-C on the server for a second or so. > The same happens for the client receiving message loop, because that one > also does not detect me suddenly interrupting or killing the server and > then loops on the empty string. > At first I thought if I caught eof-object? and then (break) the loop it > would solve the problem, but apparently it does not. > Basically I would like the server and client to be prepared for non > proper shutdown of either. > > How can I handle / detect abrupt connection losses, so that I can break > the message handling loop?
The POSIX recv() function returns 0 on end of file (connection closed) so I expect the scheme recv! procedure does the same. So on end-of-file your code appears to be producing an endless supply of empty strings. More generally, you will find it easier to use something like the get-line procedure to read text, or something like get-bytevector-n or get-bytevector-n! for reading binary records. recv! only really becomes important when the flags argument is meaningful. Rather than starting a new thread for each connection, you will get much better scalability if you use something like fibers ( https://github.com/wingo/fibers/ ), guile-a-sync2 ( https://github.com/ChrisVine/guile-a-sync2/ ) or 8sync ( https://www.gnu.org/software/8sync/ ). Chris