Path: csiph.com!usenet.pasdenom.info!weretis.net!feeder4.news.weretis.net!rt.uk.eu.org!newsfeed.xs4all.nl!newsfeed3.news.xs4all.nl!xs4all!newsgate.cistron.nl!newsgate.news.xs4all.nl!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.015 X-Spam-Evidence: '*H*': 0.97; '*S*': 0.00; 'detect': 0.07; 'encoded': 0.07; 'json': 0.07; 'socket': 0.07; 'data):': 0.09; 'msg': 0.09; 'prefix': 0.09; 'terminated': 0.09; 'subject:How': 0.10; 'python': 0.11; 'def': 0.12; 'client:': 0.16; 'closure,': 0.16; 'decode(self,': 0.16; 'from:addr:rosuav': 0.16; 'from:name:chris angelico': 0.16; 'localhost': 0.16; 'read()': 0.16; 'sane': 0.16; 'wrote:': 0.18; 'bit': 0.19; 'example': 0.22; '(in': 0.22; 'aug': 0.22; 'print': 0.22; 'error': 0.23; 'lets': 0.24; 'sends': 0.24; 'paul': 0.24; 'question': 0.24; 'source': 0.25; 'header:In-Reply- To:1': 0.27; 'am,': 0.29; "doesn't": 0.30; 'message- id:@mail.gmail.com': 0.30; "i'm": 0.30; 'code': 0.31; 'getting': 0.31; 'comments': 0.31; 'depth': 0.31; 'figure': 0.32; 'running': 0.33; 'call.': 0.33; 'not.': 0.33; 'message.': 0.35; 'connection': 0.35; 'something': 0.35; 'but': 0.35; 'received:google.com': 0.35; 'module.': 0.36; 'doing': 0.36; 'subject:?': 0.36; 'should': 0.36; 'error.': 0.37; 'remote': 0.38; 'system,': 0.38; 'server': 0.38; 'depends': 0.38; 'filter': 0.38; 'handle': 0.38; 'to:addr:python- list': 0.38; 'issue': 0.38; 'use.': 0.39; 'to:addr:python.org': 0.39; 'major': 0.40; 'how': 0.40; 'eventually': 0.60; 'length': 0.61; 'entire': 0.61; 'simply': 0.61; 'simple': 0.61; "you're": 0.61; 'you.': 0.62; 'back': 0.62; "you'll": 0.62; 'maximum': 0.63; 'taking': 0.65; 'frequently': 0.68; 'below:': 0.68; 'blow': 0.84; 'presumably': 0.84; 'shutdown': 0.84; 'subject:check': 0.84; 'you;': 0.84; 'reliable,': 0.93; '2013': 0.98 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :content-type; bh=bI8Lk/G/DTnK8jA4S/jYdYN4GbCfg/K2r0yQil2pMv8=; b=lwXuUa9P1e483Za7xm1vK5BPkkfI5cVa4P2stoiwZGOwlHG7NcC1fGbQ7Iy8PQjjr5 F3elHhK57giotOe4R1JTDwJVHUJonC5seJjvCxs0Nh3bIv9RhrVCdeI3R3v9D9n3u7gO C7j4U7f5JKegQ11vnZGd9/G20YCY1xyFhz8xbiHDx3VdxqHKj5bn/X7dhTkAsKr+A336 djiujZemODmqcVNTnjK56YsaAVxy66MJbE+qI0rm96vy4CziFkeRPDlA7zqv74pbRX7m bOFO0qzlKBfKCdNLYroPe20gJsrKa6DJIl3Nl9+5othmJsPHmFQk8pk3dnIeiIFE/XIF vRmA== MIME-Version: 1.0 X-Received: by 10.220.237.208 with SMTP id kp16mr16375320vcb.4.1377547774666; Mon, 26 Aug 2013 13:09:34 -0700 (PDT) In-Reply-To: References: Date: Tue, 27 Aug 2013 06:09:34 +1000 Subject: Re: How to check client shutdown? From: Chris Angelico To: python-list@python.org Content-Type: text/plain; charset=ISO-8859-1 X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 49 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1377547782 news.xs4all.nl 15949 [2001:888:2000:d::a6]:49725 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:53014 On Tue, Aug 27, 2013 at 5:45 AM, Paul Pittlerson wrote: > I'm currently learning about the socket module. My question is how can I detect if a connection is closed from the other side, for example a KeyboardInterrupt as I frequently use. My code below: > Once the remote end has terminated (as it will presumably do in this case), any attempt to write to the socket will eventually result in an error. You should be able to see that by simple experimentation. Be aware that it might take a bit of time for the error to filter back to you; it depends on whether the remote end actually sends back a RST (reset) packet or not. (In a sane system, hitting Ctrl-C should result in a clean shutdown and proper socket closure, but your server needs to handle the case where it doesn't get one.) Play around with it, you should be able to figure out what it's doing for you. A couple of tangential comments about your script: > ########################################################## > #server script: > > def decode(self, data): > return pickle.loads(data) MAJOR security issue here. You are taking data from a networked source and running it through a trusting system (pickle). This is NOT recommended. Also: You're using a stream socket, and depending - I think - on getting an entire message in a single read() call. This is definitely not guaranteed, though when you're working with localhost it's likely to be true. To make this reliable, you'll need to do something like prefix the message with its length (eg a Hollerith string), or use some system like JSON that lets you detect the end of the message. >From the client: > def loop(): > print 'Enter message:' > msg = raw_input() > encoded = pickle.dumps(msg) > connection.send(encoded) > loop() > > loop() Why recurse? Why not simply loop? No Python has tail-call optimization (as far as I know), so this will eventually blow up with a RuntimeError: maximum recursion depth exceeded. ChrisA