title: OSError: [Errno 9] Bad file descriptor with socket.shutdown()
body: <p>I'm currently trying to get a hang of how sockets work.</p>
  <p>I've followed an <a href="https://realpython.com/python-sockets/" rel="nofollow noreferrer">online tutorial</a> &amp; the <a href="https://docs.python.org/3/howto/sockets.html" rel="nofollow noreferrer">python HOWTO</a></p>
  <p>I have a server:</p>
  <pre><code>#!/usr/bin/env python3
      
  import socket
  
  HOST = '127.0.0.1' #standard loopback interface address (localhost)
  PORT = 9999
  
  serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  serversocket.bind((HOST, PORT))
  serversocket.listen()
  (clientsocket, address) = serversocket.accept()
  with clientsocket:
      print('Connected by', address)
      while True:
          data = clientsocket.recv(1024)
          if not data:
              break
          clientsocket.sendall(data)
  clientsocket.shutdown(socket.SHUT_RDWR)
  clientsocket.close()
  </code></pre>
  <p>and a client:</p>
  <pre><code>#!/usr/bin/env python3
  
  import socket
  
  HOST = '127.0.0.1' #server hostname or IP address
  PORT = 9999
  
  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  s.connect((HOST, PORT))
  s.sendall(b'Hello world!')
  data = s.recv(1024)
  s.shutdown(socket.SHUT_RDWR)
  s.close
  
  print('Received', repr(data))
  </code></pre>
  <p>The server listens for a connection, accepts it and echos whatever it receives.</p>
  <p>In the python HOWTO it was emphasized to always close a socket.</p>
  <p>Now when I run both scripts in seperate terminals the client does as expected:</p>
  <pre><code>Received b'Hello world!'
  </code></pre>
  <p>The terminal with the server gives me the following error:</p>
  <pre><code>Connected by ('127.0.0.1, 42780')
  Traceback (most recent call last):
      File &quot;echo-server.py&quot;, line 19, in &lt;module&gt;
          clientsocket.shutdown(socket.SHUT_RDWR)
  OSError: [Errno 9] Bad file descriptor
  </code></pre>
  <p>From looking around stackeoverflow I learned that
  <a href="https://stackoverflow.com/questions/45506392/python-sockets-oserror-errno-9-bad-file-descriptor">it was because of closing the Python file from &quot;the outside&quot;, i.e. not from the file object's close()</a> and I assume this means the socket I am trying to call <code>socket.shutdown()</code> on has already been shutdown.</p>
  <p>Now when I comment line 19 out in the server script</p>
  <pre><code>#clientsocket.shutdown(socket.SHUT_RWDR)
  </code></pre>
  <p>everything works as expected without any errors.</p>
  <p>The terminals show</p>
  <pre><code>Connected by ('127.0.0.1, 42780')
  </code></pre>
  <p>and</p>
  <pre><code>Received b'Hello world!'
  </code></pre>
  <p>From my understanding this behaviour is caused by the with statement.</p>
  <p>Now to my actual questions:</p>
  <ol>
  <li>Does the with statement make calling <code>socket.shutdown()</code> unnecessary by completing that task itself?</li>
  <li>If so, is calling <code>socket.close()</code> still necessary or is that done by the with statement aswell? (Commenting that line out didn't give me any different results)</li>
  </ol>
  <p>In the end I want to make sure how to close a socket properly from the start since the HOWTO put much emphasis on proper form.</p>