diff options
author | Fred Drake <fdrake@acm.org> | 2000-08-16 14:14:32 (GMT) |
---|---|---|
committer | Fred Drake <fdrake@acm.org> | 2000-08-16 14:14:32 (GMT) |
commit | a6070f0221c0f4f2bb0fea518ea6e0b5e9497271 (patch) | |
tree | 8cdc385a880374b8870f9a9aa05779ecd9f7eadc /Lib/socket.py | |
parent | 1582a3ab98b9792ae719e9b0bffdbdab9302f565 (diff) | |
download | cpython-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.py | 237 |
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 |