On 21.06.2018 18:00, guile-user-requ...@gnu.org wrote: > Message: 5 > Date: Thu, 21 Jun 2018 16:08:20 +0100 > From: Chris Vine <vine35792...@gmail.com> > To: guile-user@gnu.org > Subject: Re: How to notice abrupt tcp connection losses in > server/client? > Message-ID: <20180621160820.1359196e2d30873d4a3cc...@gmail.com> > Content-Type: text/plain; charset=US-ASCII > > 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. I actually tried to (break) the loop when the received message is (eof-object? ...), but it might be that I used this predicate at the wrong place (directly inside the loop when the message was already copied from the receive-buffer, instead of when recv!, I believe), now that I think about it … and maybe that is why (break)ing the loop did not work. Need to investigate more. > 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. Ah ok, thanks for the advice! I thought recv! was the way to go, as it worked so nicely so far. > 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/ ). Yep =) I am aware. I already wrote a comment inside the code noting that this new thread thing is probably not so good. Not sure I should introduce fibers into this example code yet though. And looking at fibers and 8sync is on my to-do list ; ) > Chris I will try these things and see how it goes. Thanks!
~ Zelphir