summaryrefslogtreecommitdiffstats
path: root/Lib/socket.py
diff options
context:
space:
mode:
authorFred Drake <fdrake@acm.org>2000-08-16 14:14:32 (GMT)
committerFred Drake <fdrake@acm.org>2000-08-16 14:14:32 (GMT)
commita6070f0221c0f4f2bb0fea518ea6e0b5e9497271 (patch)
tree8cdc385a880374b8870f9a9aa05779ecd9f7eadc /Lib/socket.py
parent1582a3ab98b9792ae719e9b0bffdbdab9302f565 (diff)
downloadcpython-a6070f0221c0f4f2bb0fea518ea6e0b5e9497271.zip
cpython-a6070f0221c0f4f2bb0fea518ea6e0b5e9497271.tar.gz
cpython-a6070f0221c0f4f2bb0fea518ea6e0b5e9497271.tar.bz2
Revise the wrapper structure for the socket module:
socket.py is used for all platforms, and it defines the additional classes and alternate socket() function for Windows and BeOS systems. The plat-*/socket.py files are no longer needed, since there is a shared socket.py. make_fqdn() is provided, but I decided to call it getfqdn() to be consistent with the other names in the socket module. Since it is really a "get" operation and does not create a new name, this is the right name to give it. Move the docstring here from the _socket module.
Diffstat (limited to 'Lib/socket.py')
-rw-r--r--Lib/socket.py237
1 files changed, 237 insertions, 0 deletions
diff --git a/Lib/socket.py b/Lib/socket.py
new file mode 100644
index 0000000..3cc8d91
--- /dev/null
+++ b/Lib/socket.py
@@ -0,0 +1,237 @@
+# Wrapper module for _socket, providing some additional facilities
+# implemented in Python.
+
+"""\
+This module provides socket operations and some related functions.
+On Unix, it supports IP (Internet Protocol) and Unix domain sockets.
+On other systems, it only supports IP.
+
+Functions:
+
+socket() -- create a new socket object
+fromfd() -- create a socket object from an open file descriptor [*]
+gethostname() -- return the current hostname
+gethostbyname() -- map a hostname to its IP number
+gethostbyaddr() -- map an IP number or hostname to DNS info
+getservbyname() -- map a service name and a protocol name to a port number
+getprotobyname() -- mape a protocol name (e.g. 'tcp') to a number
+ntohs(), ntohl() -- convert 16, 32 bit int from network to host byte order
+htons(), htonl() -- convert 16, 32 bit int from host to network byte order
+inet_aton() -- convert IP addr string (123.45.67.89) to 32-bit packed format
+inet_ntoa() -- convert 32-bit packed format IP to string (123.45.67.89)
+ssl() -- secure socket layer support (only available if configured)
+
+ [*] not available on all platforms!
+
+Special objects:
+
+SocketType -- type object for socket objects
+error -- exception raised for I/O errors
+
+Integer constants:
+
+AF_INET, AF_UNIX -- socket domains (first argument to socket() call)
+SOCK_STREAM, SOCK_DGRAM, SOCK_RAW -- socket types (second argument)
+
+Many other constants may be defined; these may be used in calls to
+the setsockopt() and getsockopt() methods.
+"""
+
+from _socket import *
+
+import os, sys
+
+if (sys.platform.lower().startswith("win")
+ or os.uname()[0] == "BeOS"):
+
+ # be sure this happens only once, even in the face of reload():
+ try:
+ _realsocketcall
+ except NameError:
+ _realsocketcall = socket
+
+ def socket(family, type, proto=0):
+ return _socketobject(_realsocketcall(family, type, proto))
+
+
+# WSA error codes
+if sys.platform.lower().startswith("win"):
+ errorTab = {}
+ errorTab[10004] = "The operation was interrupted."
+ errorTab[10009] = "A bad file handle was passed."
+ errorTab[10013] = "Permission denied."
+ errorTab[10014] = "A fault occurred on the network??" # WSAEFAULT
+ errorTab[10022] = "An invalid operation was attempted."
+ errorTab[10035] = "The socket operation would block"
+ errorTab[10036] = "A blocking operation is already in progress."
+ errorTab[10048] = "The network address is in use."
+ errorTab[10054] = "The connection has been reset."
+ errorTab[10058] = "The network has been shut down."
+ errorTab[10060] = "The operation timed out."
+ errorTab[10061] = "Connection refused."
+ errorTab[10063] = "The name is too long."
+ errorTab[10064] = "The host is down."
+ errorTab[10065] = "The host is unreachable."
+del os, sys
+
+
+def getfqdn(name=''):
+ """Get fully qualified domain name from name.
+
+ An empty argument is interpreted as meaning the local host.
+
+ First the hostname returned by gethostbyaddr() is checked, then
+ possibly existing aliases. In case no FQDN is available, hostname
+ is returned.
+ """
+ name = name.strip()
+ if len(name) == 0:
+ name = gethostname()
+ try:
+ hostname, aliases, ipaddrs = gethostbyaddr(name)
+ except error:
+ pass
+ else:
+ aliases.insert(0, hostname)
+ for name in aliases:
+ if '.' in name:
+ break
+ else:
+ name = hostname
+ return name
+
+
+#
+# These classes are used by the socket() defined on Windows and BeOS
+# platforms to provide a best-effort implementation of the cleanup
+# semantics needed when sockets can't be dup()ed.
+#
+# These are not actually used on other platforms.
+#
+
+class _socketobject:
+
+ def __init__(self, sock):
+ self._sock = sock
+
+ def close(self):
+ self._sock = 0
+
+ def __del__(self):
+ self.close()
+
+ def accept(self):
+ sock, addr = self._sock.accept()
+ return _socketobject(sock), addr
+
+ def dup(self):
+ return _socketobject(self._sock)
+
+ def makefile(self, mode='r', bufsize=-1):
+ return _fileobject(self._sock, mode, bufsize)
+
+ _s = "def %s(self, *args): return apply(self._sock.%s, args)\n\n"
+ for _m in ('bind', 'connect', 'connect_ex', 'fileno', 'listen',
+ 'getpeername', 'getsockname',
+ 'getsockopt', 'setsockopt',
+ 'recv', 'recvfrom', 'send', 'sendto',
+ 'setblocking',
+ 'shutdown'):
+ exec _s % (_m, _m)
+
+
+class _fileobject:
+
+ def __init__(self, sock, mode, bufsize):
+ self._sock = sock
+ self._mode = mode
+ if bufsize < 0:
+ bufsize = 512
+ self._rbufsize = max(1, bufsize)
+ self._wbufsize = bufsize
+ self._wbuf = self._rbuf = ""
+
+ def close(self):
+ try:
+ if self._sock:
+ self.flush()
+ finally:
+ self._sock = 0
+
+ def __del__(self):
+ self.close()
+
+ def flush(self):
+ if self._wbuf:
+ self._sock.send(self._wbuf)
+ self._wbuf = ""
+
+ def fileno(self):
+ return self._sock.fileno()
+
+ def write(self, data):
+ self._wbuf = self._wbuf + data
+ if self._wbufsize == 1:
+ if '\n' in data:
+ self.flush()
+ else:
+ if len(self._wbuf) >= self._wbufsize:
+ self.flush()
+
+ def writelines(self, list):
+ filter(self._sock.send, list)
+ self.flush()
+
+ def read(self, n=-1):
+ if n >= 0:
+ k = len(self._rbuf)
+ if n <= k:
+ data = self._rbuf[:n]
+ self._rbuf = self._rbuf[n:]
+ return data
+ n = n - k
+ L = [self._rbuf]
+ self._rbuf = ""
+ while n > 0:
+ new = self._sock.recv(max(n, self._rbufsize))
+ if not new: break
+ k = len(new)
+ if k > n:
+ L.append(new[:n])
+ self._rbuf = new[n:]
+ break
+ L.append(new)
+ n = n - k
+ return "".join(L)
+ k = max(512, self._rbufsize)
+ L = [self._rbuf]
+ self._rbuf = ""
+ while 1:
+ new = self._sock.recv(k)
+ if not new: break
+ L.append(new)
+ k = min(k*2, 1024**2)
+ return "".join(L)
+
+ def readline(self, limit=-1):
+ data = ""
+ i = self._rbuf.find('\n')
+ while i < 0 and not (0 < limit <= len(self._rbuf)):
+ new = self._sock.recv(self._rbufsize)
+ if not new: break
+ i = new.find('\n')
+ if i >= 0: i = i + len(self._rbuf)
+ self._rbuf = self._rbuf + new
+ if i < 0: i = len(self._rbuf)
+ else: i = i+1
+ if 0 <= limit < len(self._rbuf): i = limit
+ data, self._rbuf = self._rbuf[:i], self._rbuf[i:]
+ return data
+
+ def readlines(self):
+ list = []
+ while 1:
+ line = self.readline()
+ if not line: break
+ list.append(line)
+ return list