diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index 618aa09314b..5314039e101 100644 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -597,10 +597,9 @@ correspond to Unix system calls applicable to sockets. arguments are interpreted the same way as by the built-in :func:`open` function. - The returned file object references a :cfunc:`dup`\ ped version of the - socket file descriptor, so the file object and socket object may be - closed or garbage-collected independently. The socket must be in - blocking mode (it can not have a timeout). + Closing the file object won't close the socket unless there are no + remaining references to the socket. The socket must be in blocking mode + (it can not have a timeout). .. method:: socket.recv(bufsize[, flags]) diff --git a/Lib/socket.py b/Lib/socket.py index a2df89132f4..f94c4691001 100644 --- a/Lib/socket.py +++ b/Lib/socket.py @@ -195,6 +195,13 @@ class SocketIO(io.RawIOBase): the raw I/O interface on top of a socket object. """ + # One might wonder why not let FileIO do the job instead. There are two + # main reasons why FileIO is not adapted: + # - it wouldn't work under Windows (where you can't used read() and + # write() on a socket handle) + # - it wouldn't work with socket timeouts (FileIO would ignore the + # timeout and consider the socket non-blocking) + # XXX More docs def __init__(self, sock, mode): @@ -209,22 +216,40 @@ class SocketIO(io.RawIOBase): self._writing = "w" in mode def readinto(self, b): + """Read up to len(b) bytes into the writable buffer *b* and return + the number of bytes read. If the socket is non-blocking and no bytes + are available, None is returned. + + If *b* is non-empty, a 0 return value indicates that the connection + was shutdown at the other end. + """ self._checkClosed() self._checkReadable() return self._sock.recv_into(b) def write(self, b): + """Write the given bytes or bytearray object *b* to the socket + and return the number of bytes written. This can be less than + len(b) if not all data could be written. If the socket is + non-blocking and no bytes could be written None is returned. + """ self._checkClosed() self._checkWritable() return self._sock.send(b) def readable(self): + """True if the SocketIO is open for reading. + """ return self._reading and not self.closed def writable(self): + """True if the SocketIO is open for writing. + """ return self._writing and not self.closed def fileno(self): + """Return the file descriptor of the underlying socket. + """ self._checkClosed() return self._sock.fileno() @@ -237,6 +262,9 @@ class SocketIO(io.RawIOBase): return self._mode def close(self): + """Close the SocketIO object. This doesn't close the underlying + socket, except if all references to it have disappeared. + """ if self.closed: return io.RawIOBase.close(self)