[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: How to notice abrupt tcp connection losses in server/client?
From: |
Chris Vine |
Subject: |
Re: How to notice abrupt tcp connection losses in server/client? |
Date: |
Thu, 21 Jun 2018 16:08:20 +0100 |
On Thu, 21 Jun 2018 08:22:36 +0200
Zelphir Kaltstahl <address@hidden> 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